首页 > 代码库 > setTimeout原理

setTimeout原理

setInterval和setTimeout是前端开发中经常会用到的定时器,下面对其原理进行一下分析。

 

javascript是单线程的,一个javascript运行时包含了一个待处理的消息队列,每条消息都代表要运行的函数。当调用栈为空时,会从队列里取出条消息进行处理。

setTimeout方法包含两个参数,第一个参数为一个函数或者一个会作为eval()方法参数的js代码字符串,第二个参数为以毫秒为单位的时间。该方法的实际作用即:在一定时间之后,把一个函数加入消息队列末尾。如果这个时间点消息队列中还存在其他消息,那么该函数会在排在他之前的消息都执行完之后再开始执行。所以,这个时间会小于等于该函数开始运行的时间。

 技术分享

如上图所示,函数a,b,c执行时间均为300ms,a在执行setTimeout时开始执行。在400ms之后,c加入了消息队列,但此时调用栈中函数b仍在执行,c只能等b执行完之后才能开始执行,所以c从加入队列之后第600ms才开始执行。

 

 1 setTimeout(function() {
 2     console.timeEnd(‘setTimeout实际等待时间:‘);
 3 },1000)
 4 console.time(‘setTimeout实际等待时间:‘);
 5 
 6 console.time("执行循环时间:");
 7 for (let i = 0; i < 10000; i++) {
 8     console.log(i);
 9 }
10 console.timeEnd("执行循环时间:");

以上代码,在开始时在消息队列里加入一个函数,并开始计时。该函数被放在了队列的末尾,排在循环之后。于是循环会先执行,在循环和console语句执行完之后,setTimeout中的函数才会被执行。把该段代码该段代码在chrome中执行,最后的结果如下图:

 技术分享

可见,setTimeout中的函数是在循环及console函数执行完之后才开始执行。

 

我们有时会在代码中看到如下代码:

 setTimeout(func, 0)

现在我们就可以理解该函数的意思了。这个函数的作用就是把func函数放到队列的末尾,在所有函数都执行完之后再执行。

1 setTimeout(function() {
2    console.log(‘setTimeout‘) 
3 })
4 console.log(‘test1‘);
5 console.log(‘test2‘);
6 
7 // test1
8 // test2
9 // setTimeout

 

 

setInterval函数的原理与setInterval是相同的,就不再赘述。

setTimeout原理