JavaScript 提供定时执行代码的功能,叫作 定时器(timer)。ajax
主要由 setTimeout() 和 setInterval() 这两个函数来完成。它们向任务队列添加定时任务浏览器
var timerId = setTimeout( func()|code, delay);
第一个参数 func() | code 是将要推迟执行的函数名或者一段代码服务器
第二个参数 delay是推迟执行的毫秒数app
console.log(1); setTimeout('console.log(2)',1000); console.log(3); // 1 // 3 // 2
上面代码会 先输出 1 和 3,而后等待 1000毫秒 再输出 2函数
function f() { console.log(2); } setTimeout(f, 1000);
setTimeout(function (a,b) { console.log(a + b); }, 1000, 1, 1); // 1秒钟后打印 '2'
var x = 1; var obj = { x: 2, y: function () { console.log(this.x); } }; setTimeout(obj.y, 1000); // 1 打印的是全局变量 x
var x = 1; var obj = { x: 2, y: function () { console.log(this.x); } }; setTimeout(function () { obj.y(); }, 1000); // 2 打印的是 obj 对象的属性 x
var x = 1; var obj = { x: 2, y: function () { console.log(this.x); } }; setTimeout(obj.y.bind(obj), 1000)
var aDiv = document.getElementById('a_div'); var opacity = 1; var flag = true; var brath = setInterval(function() { if (opacity >= 0 && flag ) { opacity -= 0.1; } else { opacity += 0.1; } aDiv.style.opacity = opacity; if(opacity < 0 || opacity > 1){ flag = !flag; } }, 200);
上面代码是让一个div 透明度慢慢下降,而后又慢慢增高。。。呼吸的效果性能
var hash = window.location.hash; var hashWatcher = setInterval(function() { if (window.location.hash != hash) { updatePage(); } }, 1000);
var i = 1; var timer = setTimeout(function f() { // ... timer = setTimeout(f, 2000); // 能够确保,下一次执行老是在本次执行结束以后的2000毫秒开始 }, 2000);
var id1 = setTimeout(f, 1000); var id2 = setInterval(f, 1000); clearTimeout(id1); clearInterval(id2); // 上面代码中,回调函数f不会再执行了,由于两个定时器都被取消了
function f() {} setTimeout(f, 1000); // 10 setTimeout(f, 1000); // 11 setTimeout(f, 1000); // 12
(function() { var gid = setInterval(clearAllTimeouts, 0); function clearAllTimeouts() { var id = setTimeout(function() {}, 0); while (id > 0) { if (id !== gid) { clearTimeout(id); } id--; } } })();
先调用setTimeout
,获得一个计算器编号,而后把编号比它小的计数器所有取消this
$('textarea').on('keydown', ajaxAction);
这样写有一个很大的缺点,就是若是用户连续击键,就会连续触发keydown
事件,形成大量的 Ajax 通讯。spa
// 假定两次 Ajax 通讯的间隔不得小于2500毫秒,上面的代码能够改写成下面这样 $('textarea').on('keydown', debounce(ajaxAction, 2500)); function debounce(fn, delay){ var timer = null; // 声明计时器 return function() { var context = this; var args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); }; }
只要在2500毫秒以内,用户再次击键,就会取消上一次的定时器,而后再新建一个定时器。这样就保证了回调函数之间的调用间隔,至少是2500毫秒code
setTimeout(someTask, 100); veryLongTask(); // 上面代码的setTimeout,指定100毫秒之后运行一个任务。 // 可是,若是后面的veryLongTask函数(同步任务)运行时间很是长,过了100毫秒还没法结束,那么被推迟运行的someTask就只有等着,等到veryLongTask运行结束,才轮到它执行
setInterval
的例子
setInterval(function () { console.log(2); }, 1000); sleep(3000); function sleep(ms) { var start = Date.now(); while ((Date.now() - start) < ms) { } }
// 上面代码中,setInterval要求每隔1000毫秒,就输出一个2。
// 可是,紧接着的sleep语句须要3000毫秒才能完成,那么setInterval就必须推迟到3000毫秒以后才开始生效。
// 注意,生效后setInterval不会产生累积效应,即不会一会儿输出三个2,而是只会输出一个2。
setTimeout(function () { console.log(1); }, 0); console.log(2); // 2 // 1
上面代码先输出2,再输出1。由于2是同步任务,在本轮事件循环执行,而1是下一轮事件循环执行对象
// HTML 代码以下 // <input type="button" id="myButton" value="click"> var input = document.getElementById('myButton'); input.onclick = function A() { setTimeout(function B() { input.value +=' input'; }, 0) }; document.body.onclick = function C() { input.value += ' body' };
上面代码在点击按钮后,先触发回调函数 A ,而后触发函数 C 。
函数 A 中,setTimeout() 将函数 B() 推迟到下一轮事件循环执行,这样就起到了,先触发父元素的 回调函数 C() 的目的了
// HTML 代码以下 // <input type="text" id="input-box"> document.getElementById('input-box').onkeypress = function (event) { this.value = this.value.toUpperCase(); }
// 上面代码想在用户每次输入文本后,当即将字符转为大写。
// 可是实际上,它只能将本次输入前的字符转为大写,
// 由于浏览器此时还没接收到新的文本,因此 this.value 取不到最新输入的那个字符
document.getElementById('input-box').onkeypress = function() { var self = this; setTimeout(function() { self.value = self.value.toUpperCase(); }, 0); }
上面代码将代码放入setTimeout之中,就能使得它在浏览器接收到文本以后触发
var div = document.getElementsByTagName('div')[0]; // 改变一个网页元素的背景色 写法一 会形成浏览器“堵塞” 由于 JavaScript 执行速度远高于 DOM,会形成大量 DOM 操做“堆积” for (var i = 0xA00000; i < 0xFFFFFF; i++) { div.style.backgroundColor = '#' + i.toString(16); } // 改变一个网页元素的背景色 写法二 的好处,解决了上面的问题 var timer; var i=0x100000; function func() { timer = setTimeout(func, 0); div.style.backgroundColor = '#' + i.toString(16); if (i++ == 0xFFFFFF){ clearTimeout(timer); } } timer = setTimeout(func, 0);setTimeout(f, 0)