setTimeout()和setInterval()的区别

一、定时器

通常我们使用setTimeout()和setInterval()来创建定时器。一般情况下setTimeout()用于延迟执行某方法或功能,setInterval()则一般用于刷新表单,对于一些表单的假实时指定时间刷新同步。setTimeout()在指定的毫秒数后就会执行,而setInterval()则在每隔指定的毫秒数执行。也就是说setTimeout()执行一次,而setInterval()可以循环执行。

很多人对Javascript的定时器存在普遍的误解,认为它们是线程,事实上,Javascript是运行于单线程的环境中的。定时器仅仅只是计划代码在未来的某个时间执行,执行时机是不能保证的。在Javascript中没有任何代码是立刻执行的,但一旦进程空闲则尽快执行。

给队列添加代码并不意味着对它立刻执行,而只能表示它会尽快执行。比如,设定一个150ms后执行的定时器不代表到了150ms代码就立刻执行,它表示代码会在150ms后被加入到队列中。如果在这个时间点上,队列中没有其它东西,那么这段代码就会被执行,表面上看上去好像代码就在精确指定的时间点上执行了。其它情况下,代码可能明显地等待更长事件才执行。

所以,关于定时器,要记住的最重要的一点是,指定的时间间隔表示何时将定时器的代码添加到队列,而不是何时实际执行代码

二、setTimeout()

我们来看一个例子:

var btn = document.getElementById('mybtn');
btn.onclick = function(){
    setTimeout(function(){
        //执行某些操作
    },250);
//其它代码
};
 
 

在这里给一个按钮设置了一个事件处理程序。事件处理程序设置了一个250ms后调用的定时器。点击该按钮后,首先将onclick事件处理程序假如队列。该程序执行后才设置定时器,再有250ms后,指定的代码才被添加到队列中等待执行。

如果onclick事件处理程序执行了300ms,那么定时器的代码至少要在定时器设置之后的300ms后才会被执行。队列中所有的代码都要等等Javascript进程空闲之后才能执行,而不管它们是如何添加到队列中的

所以我们来看一下这段代码:

console.log('one');
setTimeout(function(){
  console.log('two');
},0);
console.log('three');	
执行结果是什么呢?答案就应该是one three two

三、setInterval()

使用setInterval()创建的定时器确保了定时器代码规则地插入到队列中。这个方式的问题在于,定时器代码可能在代码再次被添加到队列之前还没有完成执行,结果导致定时器代码连续运行好几次,而之间没有任何停顿。

使用setInterval()创建定时器会有两个问题:

(1)某些间隔会被跳过

(2)多个定时器的代码执行之间的间隔可能会比预期的小

假设,某个onclick事件处理程序使用setInterval()设置了一个200ms间隔的重复定时器。如果事件处理程序花了300ms多一点的事件完成,同时定时器代码也花了差不多的时间,就会同时出现跳过间隔且连续执行定时器代码的情况

为了避免setInterval()的这两个缺点,可以使用链式setTimeout()调用

setTimeout(function () {
   // 处理中
    setTimeout(arguments.callee,interval);
},interval);

这个模式链式调用了setTimeout(),每次函数执行的时候都会创建一个新的定时器。第二个setTimeout()调用使用了arguments.callee来获取对当前执行的函数的引用,并为其设置另外一个定时器。这样做的好处是,在前一个定时器代码执行完之前,不会想队列插入新的定时器代码,确保不会有任何缺失的间隔。而且,可以保证在下一次定时器代码执行之前,至少要等等指定的间隔,避免了连续的运行。

参考资料:

    《Javascript高级程序设计》    Nicholas C.Zakas著

猜你喜欢

转载自blog.csdn.net/KysonLai/article/details/79965660