event loop(事件循环) 一 深入理解

如果面试官问你 JS中的event loop是什么?我相信大多数人都能答出来JS是单线程语言,只有一个主线程执行,执行栈,同步、异步之类。但是,这样的理解只是浅层的,如果面试官要你再深入解释,我相信大多数人都卡住了,不知道还能解释什么,那么,问题来了,这种情况怎么办?

来看这篇文章,看完了你就知道怎么办了。

JS页面的任务不仅可以按照同步异步来分,也可以分为macro-taskmicro-task

macro-task都有:包括整体代码script,setTimeout,setInterval
micro-task都有:Promise,process.nextTick

页面初始化时,不同的任务会进入到不同的 Event Queue(事件队列)

初始化时,会执行所有代码,将setTimeout等加入到macro-task的事件列表,将Promise等加入到micro-task事件列表。
遇到立即执行的代码,则立即执行,之后,会将事件列表中所有的micro-task都执行完毕。

第一轮事件循环结束。

第二轮事件循环开始,拿出第一轮中第一个放入macro-task列表中的事件开始执行完毕

第二轮事件循环结束。

第三轮循环开始,拿出第一轮中第二个放入macro-task列表中的事件开始执行完毕

第三轮事件循环结束。

就像上面这样,反复执行,即事件循环

看了上面的解释,接下来,我们来看一个例子:

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')
    })
})

我们按照上面的理论来分析这段代码:

首先,进入到第一轮事件循环:

遇到 console.log('1') 输出 '1'

遇到 setTimeout,将其回调函数加入到 macro-task 事件列表,记为 setTimeout1

遇到 process.nextTick,将其回调函数加入到 micro-task 事件列表,记为 process1

遇到 new Promise,立即执行,输出 ** '7'**,then被分发到 micro-task 事件列表,记为 then1

遇到 setTimeout 将其回调函数加入到 macro-task 事件列表,记为 setTimeout2

执行到这里,我们来数数第一轮事件循环中的任务列表:

macro-task:setTimeout1,setTimeout2

micro-task:process1, then1

将列表中所有的 micro-task 执行完毕,输出 '6','8'

第一轮事件循环正式结束。

第二轮事件循环开始:

这时,第一轮输出结果是 '1','7','6','8'

macro-task 中,拿出第一个进入的事件,即setTimeout1,将其推入到执行栈开始执行

先输出:'2'

遇到 process.nextTick,将其回调函数加入到 micro-task 事件列表,记为 process2

遇到 new Promise, 立即执行,输出 ** '4'**,将then回调函数加入到 micro-task 事件列表,记为 then2

执行到这里,我们数数第二轮事件循环中的任务列表:

macro-task:setTimeout1

micro-task:process2,then2

将列表中所有的 micro-task 执行完毕,输出:'3', '5'

第二轮事件循环结束

第三轮事件循环开始,前两轮输出为:'1','7','6','8','2','4','3', '5'

在 macro-task 中,拿出第二个进入的事件,即setTimeout2,将其推入到执行栈开始执行

先输出:'9'

遇到 process.nextTick,将其回调函数加入到 micro-task 事件列表,记为 process3

遇到 new Promise, 立即执行,输出 '11',将then回调函数加入到 micro-task 事件列表,记为 then3

执行到这里,我们数数第三轮事件循环中的任务列表:

macro-task:setTimeout2

micro-task:process3,then3

将列表中所有的 micro-task 执行完毕,输出:'10', '12'

第三轮事件循环结束。

如果还有第四轮,第五轮,则循环上面的步骤,这样的循环,即事件循环

总结执行结果:'1','7','6','8','2','4','3','5','9','11','10','12'

好,写完收工,等待下班去吃大餐。

原文作者写的更好,大家可以看看 https://juejin.im/post/59e85eebf265da430d571f89

你可能感兴趣的:(event loop(事件循环) 一 深入理解)