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 1
2020-10-15 16:10
哈哈哈
央视财经评论LV 1
2020-10-15 16:08
不错呀
经济半小时LV 1
2020-10-15 16:07
说的好
消费主张LV 1
2020-10-15 16:07
博主辛苦了
焦点访谈LV 1
2020-10-15 16:06
学到了好多知识

Warning: Cannot modify header information - headers already sent by (output started at /www/wwwroot/blog.dyboy.cn/content/templates/dyblog/footer.php:56) in /www/wwwroot/blog.dyboy.cn/include/lib/view.php on line 23