js中setTimeout和setInterval的深入理解:它们之间的区别,原理,“异步“等

时间: 2017-11-16阅读: 772标签: 定时器

setTimeout和setInterval的区别

setTimeout在执行时,是在载入后延迟指定时间后,去执行一次表达式,而setInterval则不一样,它从载入后是每隔指定的时间就执行一次表达式。当然我们可以通过重复调用setTimeout的方法,实现类似于setInterval一样达到周而复始的效果,下面我们就实现用setTimeout来模拟setInterval的效果:

function interval(fn,time){  //每隔1秒让++i
    fn();
    setTimeout(()=>{arguments.callee(fn,time);},time);//通过arguments.callee调用自身
}
//执行Interval函数
var i=0
interval(()=>{++i;console.log(i)},500); 
//重写Interval函数,从而起到关闭定时器的效果
interval = null;


setTimeout和setInterval的原理

但是需要注意的是:无论setTimeout还是setInterval里面的函数执行并不是时间到了就执行,而是:js主进程按顺序执行程序的同时,还有一个在进程空闲的时候执行的程序队列,而定时器就相当于在多少毫秒之后把回调函数放入空闲队列中去执行。如果空闲队列中同时存在其它程序,定时器中的回调执行顺序就不确定了。例如:

setTimeout(()=>{console.log("我是0秒执行")},0);
( function(){
	console.log("我是匿名函数中执行的")
})();
console.log("我在后面哦!");
//输出顺序:我是匿名函数中执行的  我在后面哦  我是0秒执行

看了上面的中输出我们会发现即使定时器中设置的时间为0,它仍然是最后输出的,由此可以看出它的时间并不是那么准确了,而是在js进程空闲的时候执行的。


setTimeout和setInterval的“异步”

通过上面我们已经知道,回调函数的执行是在多少时间插入空闲队列中并按顺序去执行,来达到延迟的效果,所以它的异步只是一个假象:它同样运行在一个线程上! 因为JS始终是单线程执行的。

那么如果在它们执行之前插入一个死循环,setTimeout和setInterval中的回调函数还会在执行吗,例如:

setTimeout(()=>{console.log("我还会执行吗?")},0); 
while(true) {};
console.log("执行不了我了!");

我们可以看到在控制台中什么都不会输出,直接是由于js是单线程,比堵塞了。而且有趣的是,你执行了这个代码,点击浏览器关闭当前页面都没反应了...


这篇文章就整理到这里了,希望对你的学习有一定的帮助。