js之Event loop

参考文章 带你彻底弄懂Event Loop
https://segmentfault.com/a/1190000016278115?utm_source=tag-newest

宏队列,macrotask,也叫tasks
一些异步任务的回调会依次进入macro task queue,等待后续被调用,这些异步任务包括:

setTimeout
setInterval
setImmediate (Node独有)
requestAnimationFrame (浏览器独有)
I/O
UI rendering (浏览器独有)

微队列,microtask,也叫jobs。
另一些异步任务的回调会依次进入micro task queue,等待后续被调用,这些异步任务包括:

process.nextTick (Node独有)
Promise
Object.observe
MutationObserver

(注:这里只针对浏览器和NodeJS)

浏览器的Event Loop
js之Event loop_第1张图片

1、执行全局Script同步代码,这些同步代码有一些是同步语句,有一些是异步语句(比如setTimeout等);
2、全局Script代码执行完毕后,调用栈Stack会清空;
3、从微队列microtask queue中取出位于队首的回调任务,放入调用栈Stack中执行,执行完后microtask queue长度减1;
4、继续取出位于队首的任务,放入调用栈Stack中执行,以此类推,直到把microtask queue中的所有任务都执行完毕。注意,如果在执行microtask的过程中,又产生了microtask,那么会加入到队列的末尾,也会在这个周期被调用执行;
5、microtask queue中的所有任务都执行完毕,此时microtask queue为空队列,调用栈Stack也为空;
6、取出宏队列macrotask queue中位于队首的任务,放入Stack中执行;
执行完毕后,调用栈Stack为空;
重复第3-7个步骤;

可以看到,这就是浏览器的事件循环Event Loop

这里归纳3个重点:

1、宏队列macrotask一次只从队列中取一个任务执行,执行完后就去执行微任务队列中的任务;
2、微任务队列中所有的任务都会被依次取出来执行,知道microtask queue为空;
3、图中没有画UI rendering的节点,因为这个是由浏览器自行判断决定的,但是只要执行UI rendering,它的节点是在执行完所有的microtask之后,下一个macrotask之前,紧跟着执行UI render。

console.log(1);

setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => {
    console.log(3)
  });
});

new Promise((resolve, reject) => {
  console.log(4)
  resolve(5)
}).then((data) => {
  console.log(data);
})

setTimeout(() => {
  console.log(6);
})

console.log(7);

执行结果

// 正确答案
1
4
7
5
2
3
6

在执行微队列microtask queue中任务的时候,如果又产生了microtask,那么会继续添加到队列的末尾,也会在这个周期执行,直到microtask queue为空停止。
注:当然如果你在microtask中不断的产生microtask,那么其他宏任务macrotask就无法执行了,但是这个操作也不是无限的,拿NodeJS中的微任务process.nextTick()来说,它的上限是1000个,后面我们会讲到。

你可能感兴趣的:(ES6,前端,javascript)