js运行机制event-loop之宏任务与微任务

有的时候在代码中设定的计时器会发现不准 有偏差 这是为什么呢 想要知道这个问题就应该先了解 js运行机制的 宏任务与 微任务
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
micro-task(微任务):Promise,process.nextTick
js运行机制event-loop之宏任务与微任务
同步和异步任务分别进入不同的执行场所 同步的进入主线成异步的进入Event Table并注册函数

当制定的事情完成时 Event Table 会将这个函数移入 Evnet Queue中

主现成的任务执行完毕为空 会去 Event Queue中度取对应的函数进入主线程

上述过程会不断重复 也就是Event loop(时间循环)
代码示范描述

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

作者:ssssyoki
链接:https://juejin.im/post/59e85eebf265da430d571f89
来源:掘金
(请注意,这是node环境下的事件监听依赖libuv与前端环境不完全相同,输出顺序可能会有误差)

第一轮事件循环流程分析如下:

整体script作为第一个宏任务进入主线程,遇到console.log,输出1。
遇到setTimeout,其回调函数被分发到宏任务Event Queue中。我们暂且记为setTimeout1。
遇到process.nextTick(),其回调函数被分发到微任务Event Queue中。我们记为process1。
遇到Promise,new Promise直接执行,输出7。then被分发到微任务Event Queue中。我们记为then1。
又遇到了setTimeout,其回调函数被分发到宏任务Event Queue中,我们记为setTimeout2。

宏任务Event Queue
微任务Event Queue

setTimeout1
process1

setTimeout2
then1

上表是第一轮事件循环宏任务结束时各Event Queue的情况,此时已经输出了1和7。

我们发现了process1和then1两个微任务。

执行process1,输出6。
执行then1,输出8。

好了,第一轮事件循环正式结束,这一轮的结果是输出1,7,6,8。那么第二轮时间循环从setTimeout1宏任务开始:

首先输出2。接下来遇到了process.nextTick(),同样将其分发到微任务Event Queue中,记为process2。new Promise立即执行输出4,then也分发到微任务Event Queue中,记为then2。

宏任务Event Queue
微任务Event Queue

setTimeout2
process2

then2

第二轮事件循环宏任务结束,我们发现有process2和then2两个微任务可以执行。
输出3。
输出5。
第二轮事件循环结束,第二轮输出2,4,3,5。
第三轮事件循环开始,此时只剩setTimeout2了,执行。
直接输出9。
将process.nextTick()分发到微任务Event Queue中。记为process3。
直接执行new Promise,输出11。
将then分发到微任务Event Queue中,记为then3。

宏任务Event Queue
微任务Event Queue

process3

then3

第三轮事件循环宏任务执行结束,执行两个微任务process3和then3。
输出10。
输出12。
第三轮事件循环结束,第三轮输出9,11,10,12。

整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。