JS事件循环(Event Loop)

2020-08-11  本文已影响0人  高级程序狗

本文是近期学习js事件循环后的总结,比较适合入门,但不一定准确,欢迎指正。文章内容大量参考以下博文,非常推荐阅读:

https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
https://juejin.im/post/6844903512845860872
https://github.com/aooy/blog/issues/5
html5 Event Loop定义

Event loop用来协调事件、用户交互、脚本、呈现、网络等,说白了就是控制js什么时候应该做什么事情。需要注意的是,event loop在nodejs和浏览器中处理方式不同,本文特指浏览器环境(一些老版本浏览器也先不提😢)。

猜猜看下面这段代码会输出什么:

console.log('script start');

setTimeout(function () {
  console.log('setTimeout');
}, 0);

Promise.resolve()
  .then(function () {
    console.log('promise1');
  })
  .then(function () {
    console.log('promise2');
  });

console.log('script end');

正常情况会按照以下顺序打印:script start, script end, promise1, promise2, setTimeout

在详细解释前,先说明几个概念:

概念比较枯燥,结合一张图来理解:

image.png
图片出处

关于之前的demo,执行过程如下(超详细版):

1、代码被添加到 Task Queue

Task Queue JS Stack MicroTask Queue
script - -

2、JS Stack 获取到 Task Queue 的第一个任务,开始执行(任务执行完成后才会从队列中移除):

Task Queue JS Stack MicroTask Queue
script script -

3、打印 script start
4、执行到 setTimeout 时,将回调添加到 Task Queue

Task Queue JS Stack MicroTask Queue
script, setTimeout script -

5、执行到 Promise.resolve().then 时,将回调添加到 MicroTask Queue

Task Queue JS Stack MicroTask Queue
script, setTimeout script then1

6、打印 script end
7、此时代码执行完成, JS Stack 为空

Task Queue JS Stack MicroTask Queue
script, setTimeout - then1

8、 MicroTask Queue 为空吗?否。所以从 MicroTask Queue 取出 Promise.resolve().then 的回调执行。

Task Queue JS Stack MicroTask Queue
script, setTimeout then1 then1

9、打印 promise1
10、遇到 Promise.resolve().then.then,添加到 MicroTask Queue

Task Queue JS Stack MicroTask Queue
script, setTimeout then1 then1, then2

11、此时代码执行完成, JS Stack 为空

Task Queue JS Stack MicroTask Queue
script, setTimeout - then2

12、MicroTask Queue 为空吗?否。所以从 MicroTask Queue 取出 then2 执行,打印 promise2

Task Queue JS Stack MicroTask Queue
script, setTimeout then2 then2

13、JS StackMicroTask Queue 均为空,本轮结束:

Task Queue JS Stack MicroTask Queue
setTimeout1 - -

1、Task Queue 取出 setTimeout 回调执行,打印 setTimeout

Task Queue JS Stack MicroTask Queue
setTimeout setTimeout -

2、全部执行完毕

Task Queue JS Stack MicroTask Queue
- - -

尝试一下更复杂的例子,分析时记得在本子上写下Task Queue | JS Stack | MicroTask Queue,记录它们的变化:

console.log('1');
setTimeout(function() {
    console.log('2');
    setTimeout(function(){console.log('3')})
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
console.log('6')
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})
setTimeout(function() {
    console.log('9');
    new Promise(function(resolve) {
        setTimeout(function(){console.log('10')})
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

结果是:1 6 7 8 2 4 5 9 11 12 3 10,轮数过多,这里暂时不做详细解释。

上一篇 下一篇

猜你喜欢

热点阅读