JavaScript Event Loop

深入了解事件循环,有助于写出更加高质量的代码。

所有会进入任何同步的代码都会进入call stack,遵循先进后出,后进先出的规则,而异步的代码在执行时才会进入Event loop队列,当JS主线程执行完毕后,且异步时机到了,就会将异步回调中的代码推入call stack执行。

异步时机什么时候到是由宿主环境(Web APIs)决定,JS主线程已经调用完毕,但如果Event loop中有内容时,就会将对应的callback queue推入call stack中,继续执行,否则JS引擎将不会再执行任何代码。

Event Loop的处理方式包含:Microtask和Macrotask(微任务和宏任务)。setTimeout为代表的宏任务,Promise为代表的微任务。

异步队列始终是周而复始地循环执行。可以看作一个二维数组:每一横排是一个队列中的每一个函数,纵排是每一个队列

Macrotask是将执行函数添加到新的纵排,Microtask是将执行函数添加到当前执行队列的横排,因此Microtask的插入是轻量的,最快被执行到的。

满足如下规则:

  • 在当前的微任务没有执行完成时,是不会执行下一个宏任务的。
  • 所有会进入的异步都是指的事件回调中的那部分代码。

一道经典的代码例子:

setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)

最后打印的结果是:1、2、3、4

解释一下:第一行代码注册了一个宏任务,相当于二维数组增加了一行,然后在promise内部执行了resolve(),这是一个异步回调,然后第5行同步代码会打印1,然后执行到第10行代码打印2,resolve()的回调是一个微任务添加到当前宏任务的尾部,因为没有其他的函数调用,所以会调用打印3,当前宏任务执行结束,最后调用settimout中的代码打印4。

网友整理的宏任务图表如下,更多请阅读参考文章:

宏任务

Reference: 微任务、宏任务与Event-Loop

发表评论 / Comment

用心评论~

金玉良言 / Appraise
腾讯视频LV 2
2020-10-15 16:03
不错学习了
她说,LV 2
2020-09-28 18:15
学到了 感谢
幻想家LV 2
2020-09-28 18:14
更新啦~