manlili blog

setInterval()和setTimeout()

setTimeout

定义和用法: setTimeout()方法用于在指定的毫秒数后调用函数或计算表达式。  
语法: setTimeout(code,millisec)  
参数: code (必需):要调用的函数后要执行的 JavaScript 代码串。millisec(必需):在执行代码前需等待的毫秒数。  
提示: setTimeout() 只执行 code 一次。如果要多次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout()。

setInterval

setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
语法: setInterval(code,millisec[,”lang”])
参数: code 必需。要调用的函数或要执行的代码串。millisec 必须。周期性执行或调用 code 之间的时间间隔,以毫秒计。
返回值: 一个可以传递给 Window.clearInterval() 从而取消对 code 的周期性执行的值。

clearInterval()和clearTimeout()

3.setInterval(),setTimeout() 会返回一个值,一般认为是ID,将这个ID值传递给clearInterval(),clearTimeout() 可以取消执行,例如:

1
2
3
4
5
6
7
var intervalTimer=setInterval(function(){
console.log(1)
},3000);
console.log(intervalTimer); //一般是一个数字,Number
button.onclick=function(){
clearInterval(intervalTimer);
};

clearInterval()和clearTimeout()其实是通用的,就是说你可以用 clearInterval() 取消 setTimeout() 执行,clearTimeout()同样可以取消 setInterval() 执行。

this

关于setInterval()和setTimeout()中回调函数中的this,setInterval(),setTimeout() 方法是浏览器 window 对象提供,所以第一个参数函数中的this指向window对象,这跟变量的作用域有关:

1
2
3
4
5
6
7
8
9
10
var a=1;
var obj={
a:2,
b:function(){
setTimeout(function(){
console.log(this.a);//这里返回的是:1;
},2000);
}
};
obj.b();

当然你可以通过使用bind()方法来改变这个情况

1
2
3
4
5
6
7
8
9
10
11
var a=1;
var obj={
a:2,
b:function(){
setTimeout(function(){
console.log(this.a);//这里返回的是:2;
}.bind(this),2000);//注意这行
}
};
obj.b();

小细节的题目

谁先执行?

1
2
3
4
setTimeout(function () {
func1();
}, 0)
func2();

func1和func2谁会先执行?这个答案应该比较简单,func2先执行,func1后面执行。

再来一题

1
2
3
4
5
6
7
setTimeout(function () {
func1()
}, 0)
setTimeout(function () {
func1()
})

有什么差别?0秒延迟,此回调将会放到一个能立即执行的时段进行触发。javascript代码大体上是自顶向下的,但中间穿插着有关DOM渲染,事件回应等异步代码,他们将组成一个队列,零秒延迟将会实现插队操作。
不写第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。

setTimeout和单线程思考

首先需要注意javascript是单线程的,特点就是容易出现阻塞。如果一段程序处理时间很长,很容易导致整个页面hold住。什么交互都处理不了怎么办?

简化复杂度?复杂逻辑后端处理?html5的多线程?

上面都是ok的做法,但是setTimeout也是处理这种问题的一把好手。

setTimeout一个很关键的用法就是分片,如果一段程序过大,我们可以拆分成若干细小的块。
例如上面的情况,我们将那一段复杂的逻辑拆分处理,分片塞入队列。这样即使在复杂程序没有处理完时,我们操作页面,也是能得到即使响应的。其实就是将交互插入到了复杂程序中执行。

换一种思路,上面就是利用setTimeout实现一种伪多线程的概念。

setTimeout这么厉害,那么我们是需要在在项目中大量使用吗?

我这边的观点是非常不建议,在我们业务中,基本上是禁止在业务逻辑中使用setTimeout的,因为我所看到的很多使用方式都是一些问题不好解决,setTimeout作为一个hack的方式。
例如,当一个实例还没有初始化的前,我们就使用这个实例,错误的解决办法是使用实例时加个setTimeout,确保实例先初始化。
为什么错误?这里其实就是使用hack的手段
第一是埋下了坑,打乱模块的生命周期
第二是出现问题时,setTimeout其实是很难调试的。

请我喝杯果汁吧!