深入了解事件循环,有助于写出更加高质量的代码。
所有会进入任何同步的代码都会进入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
版权声明:《 JavaScript Event Loop 》为DYBOY原创文章,转载请注明出处!
最后编辑:2020-9-19 15:09:53
2020-10-15 16:03
2020-09-28 18:15
2020-09-28 18:14