javascript中有两种(最常用的)定时器函数setTimeout
和setInterval
(其他)
这两种方法都具有相同的签名。他们将回调函数和延迟时间作为参数。
setTimeout
延迟后仅执行一次,而setInterval
在每个延迟毫秒后继续调用回调函数。
这两种方法都返回一个整数标识符,可用于在计时器到期之前清除它们。
clearTimeout
并且clearInterval
这两种方法都采用从上述函数返回的整数标识符setTimeout
和setInterval
例子:
设置超时
alert("before setTimeout");
setTimeout(function(){
alert("I am setTimeout");
},1000); //delay is in milliseconds
alert("after setTimeout");
如果您运行上面的代码,您将看到它发出警报before setTimeout
,然后after setTimeout
最终I am setTimeout
在 1 秒(1000 毫秒)后发出警报
您可以从示例中注意到的是,它setTimeout(...)
是异步的,这意味着它在进入下一条语句之前不会等待计时器过去,即alert("after setTimeout");
例子:
设置间隔
alert("before setInterval"); //called first
var tid = setInterval(function(){
//called 5 times each time after one second
//before getting cleared by below timeout.
alert("I am setInterval");
},1000); //delay is in milliseconds
alert("after setInterval"); //called second
setTimeout(function(){
clearInterval(tid); //clear above interval after 5 seconds
},5000);
如果您运行上面的代码,您将看到它发出警报before setInterval
,然后after setInterval
最终I am setInterval
在 1 秒(1000 毫秒)后发出 5 次警报,因为 setTimeout 会在 5 秒后清除计时器,否则每 1 秒就会I am setInterval
无限次发出警报。
浏览器内部如何做到这一点?
我将简要解释。
要了解您必须了解 javascript 中的事件队列。在浏览器中实现了一个事件队列。每当在 js 中触发事件时,所有这些事件(如 click 等)都会添加到此队列中。当您的浏览器没有要执行的内容时,它会从队列中获取一个事件并一一执行。
现在,当您调用setTimeout
或setInterval
您的回调注册到浏览器中的计时器时,它会在给定时间到期后添加到事件队列中,最终 javascript 从队列中获取事件并执行它。
之所以发生这种情况,是因为 javascript 引擎是单线程的,它们一次只能执行一件事。因此,他们无法执行其他 javascript 并跟踪您的计时器。这就是为什么这些计时器在浏览器中注册(浏览器不是单线程的)并且它可以跟踪计时器并在计时器到期后将事件添加到队列中。
仅在这种情况下才会发生同样的情况setInterval
,事件会在指定的时间间隔后一次又一次地添加到队列中,直到它被清除或刷新浏览器页面。
笔记
您传递给这些函数的延迟参数是执行回调的最小延迟时间。这是因为在计时器到期后,浏览器将事件添加到队列中以由 javascript 引擎执行,但回调的执行取决于您在队列中的事件位置,并且由于引擎是单线程的,它将执行所有事件一一排队。
因此,当您的其他代码阻塞线程并且没有给它时间处理队列中的内容时,您的回调有时可能需要超过指定的延迟时间才能被调用。
正如我提到的,javascript 是单线程的。所以,如果你长时间阻塞线程。
喜欢这段代码
while(true) { //infinite loop
}
您的用户可能会收到一条消息说页面没有响应。