资讯专栏INFORMATION COLUMN

setTimeout与setInterval(一)

Betta / 1617人阅读

摘要:看一下例子一些其他的代码假定处理程序需要执行,这时虽然在添加了定时器代码,但是仍旧需要等待事件完成后才能够执行。缺点某些间隔会被跳过多个定时器的代码执行之间的间隔可能会比预期小。

一. setTimeout 1. 定义
window.setTimeout(func,[delay,param1,param2,····]);
window.setTimeout(code,[delay]);

参数说明:
a. 对于第一行代码:
func指的是延迟后想执行的函数,delay为延迟秒数,为毫秒,最大为32位有符号整数值,超过最大值即2147483647,将导致函数被立即执行。
param是func的参数,但是这种赋予参数的方法在IE9以下(含IE9)不兼容,可以使用polyfill或者外层包裹进行兼容性处理,有兴趣可以点击这里。
b. 对于第二行代码:
code指的是可执行代码,例如

setTimeout(alert("HeiHei"),200)

但是这种方法不推荐,类似eval(),可以包含可执行代码,含有安全隐患。

2. 事件添加的说明

定时器对队列的工作方式:当特定时间过去后将代码添加到队列中,但并不意味着会马上将执行,设定一个200ms后执行的定时器,指的是在200ms后它将被添加到队列中,是否执行,还得看队列中是否没有其他的东西。看一下例子:

var a=document.getElementById("nav");
    a.onclick=function(){
    setTimeout(alertsomething,200);
    //一些其他的代码
}
function alertsomething(){
    alert("it is working");
}

假定onclick处理程序需要执行300ms,这时虽然在205ms添加了定时器代码,但是仍旧需要等待onclick事件完成后才能够执行。如图所示,本来在205ms处添加了定时器代码,但是由于此时onclick事件还没结束,故要等到300ms后才执行定时器代码

3. 清除事件
window.clearTimeout(timeoutID);
4. 对于this的影响

setTimeout调用的代码,运行在与所在函数完全分离的执行环境上,在非严格模式中,this默认指向global或window,严格模式中会抛出undefined,通过call的方式目前也无法改变,官方的示例如下:

myArray = ["zero", "one", "two"];
myArray.myMethod = function (sProperty) {
    alert(arguments.length > 0 ? this[sProperty] : this);
};
setTimeout.call(myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object"
setTimeout.call(myArray, myArray.myMethod, 2500, 2); // same error

对此我们可以使用外加一个匿名函数解决。

setTimeout(function(){myArray.myMethod()}, 2000); // prints "zero,one,two" after 2 seconds
setTimeout(function(){myArray.myMethod("1")}, 2500); // prints "one" after 2.5 seconds

其他解决方案可以参照一下参考资料。

5. 事件延迟时间大于设定值

a.上文图中所示,队列中还有事件未执行完成,需要等待
b.chrome和firefox在未激活的标签中,会减缓setTimeoutsetInterval的执行,具体原因可以参考下文的资料
c.由于浏览器精度的原因,delay的值最终大于等于4。

下面是w3c中的原文:

If the currently running task is a task that was created by the setTimeout() method, and timeout is less than 4, then increase timeout to 4.

举个例子:

 setTimeout(function() {
            alert(2);
        }, 0);
        alert(1); //先显示1,接着才显示2
二、setInterval 1.定义

跟setTimeout类似

window.setInterval(func, delay[,param1, param2, ...]);
window.setInterval(code, delay);

为了避免多个定时器代码不间断连续运行好几次,当使用setInterval(),仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中,通俗点就是等到上个定时器完成,再添加一个。

2.缺点

某些间隔会被跳过

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

在5处,创建一个定时器
205处,添加一个定时器,但是onclick代码没执行完成,等待
300处,onclick代码执行完毕,执行第一个定时器
405处,添加第二个定时器,但前一个定时器没有执行完成,等待
605处,本来是要添加第三个定时器,但是此时发现,队列中有了一个定时器,被跳过
等到第一个定时器代码执行完毕,马上执行第二个定时器,所以间隔会比预期的小。

3.解决方法

链式调用,如下图所示,主要用于重复定时器

setTimeout(function(){
    //处理代码
    setTimeout(arguments.callee,interval)
},intercal);

递归调用自己。

4. 清除事件
window.clearInterval(intervalID)
三、两者之间的区别

setTimeout方法,在一个指定的时间间隔后运行代码。
setInterval方法, 每隔一个固定的时间间隔后持续运行指定代码。

四、参考资料

MDN WindowTimers.setTimeout()

W3C Times

Chrome and Firefox throttle setTimeout/setInterval in inactive tabs

《JavaScript高级程序设计》Nicholas C.Zakas著 李松峰 曹力译

你真的了解setTimeout和setInterval吗

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90828.html

相关文章

  • process.nextTick() 、setTimeout()、setInterval() 运行机

    摘要:注意如果主逻辑的代码执行时间已经超过了第二个参数设置的时间,那么等运行到该回调函数时,它会忽略掉这个时间,并立即执行。如果某一个进行大量的计算,那么它就会阻塞在当前的回调函数中,等待该计算完成后,再执行下一个的回调函数。 setTimeout() ​ JavaScript是一个单线程的语言,也就是说它同一时间只能执行一段代码,接下来我们通过两个例子说明一下单线程语言和多线程语言的...

    lscho 评论0 收藏0
  • setTimeoutsetInterval

    摘要:工作线程执行异步任务,执行完成后把对应额回调函数封装成一条消息放到消息队列中主线程不断地从消息队列中取消息并执行。当消息队列为空时,主线程阻塞,直到消息队列再次非空。取决于何时被主线程的事件循环取到,并执行。 转自:http://palmer.arkstack.cn/201...一:平时简单使用 1.setTimeout延迟一段时间执行一次(only one) setTimeout(f...

    Tangpj 评论0 收藏0
  • JavaScript 定时器

    摘要:定时器方法相关方法有四种。返回值返回值是一个正整数,表示定时器的编号。这个值可以传递给来取消该定时器。使用方法很简单只有一个参数,该参数为您要取消定时器的标识符。用法很简单当代码运行到这行的时候,会取消所设置的定时器。 简单介绍在JavaScript中定时器有两个 setInterval() 与 setTime...

    王伟廷 评论0 收藏0
  • 定时器

    摘要:提供定时执行代码的功能,叫做定时器,主要由和这两个函数来完成。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。上面代码中,回调函数不会再执行了,因为两个定时器都被取消了。 JavaScript 提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成。它们向任务队列添加定时任务。 setTimeout()...

    Nino 评论0 收藏0
  • setTimeout-setInterval看JS线程

    摘要:提出标准,允许脚本创建多个线程,但是子线程完全受主线程控制,且不得操作。所以,这个新标准并没有改变单线程的本质。事件循环主线程线程只会做一件事,就是从消息队列里面取消息执行消息,再取消息再执行。工作线程是生产者,主线程是消费者。 最近项目中遇到了一个场景,其实很常见,就是定时获取接口刷新数据。那么问题来了,假设我设置的定时时间为1s,而数据接口返回大于1s,应该用同步阻塞还是异步?我们...

    elliott_hu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<