事件循环

Posted by Leonsux on May 17, 2022

我们都知道 js 是单线程的,靠同步任务、异步任务来模拟实现多线程。

代码执行时,同步代码正常在主线程中执行,遇到异步代码(比如异步请求或者settimeout),则进入 Event Table(交给js的运行环境来处理,浏览器或者nodejs),并将其回调函数放入 Event Queue 中(当异步行为结束时,比如计时器倒计时结束后)。

主线程代码执行完后,会去 Event Queue 中读取函数,进入主线程中执行。

console.log(1);    // 进入主线程执行,1

setTimeout(() => { // 进入 Event Table,函数放入 Event Queue
  console.log(2);
}, 1000);          // 1s后,主线程去 Event Queue 中读取函数,进入主线程中执行,2

console.log(3);    // 进入主线程执行,3

macro-task(宏任务):包括整体代码script,setTimeout,setInterval,dom操作,用户交互(鼠标、键盘事件),网络请求(ajax的onload) micro-task(微任务):Promise,process.nextTick,Object.observe,MutationObserver

其中 Promise 在某些浏览器(某个版本的Safari)中是被当做宏任务来处理的。

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

Promise.resolve().then(() => console.log('Promise then'));

console.log('globle');

遇到 setTimeout,放入宏任务 Event Queue 中。

遇到 Promise.then,放入微任务 Event Queue 中。

遇到 console.log('globle');,直接输出,宏执行结束。

看下有没有微任务,发现 Promise.then,执行输出 Promise then

所有的微任务都执行完毕,第一轮事件循环结束。

执行宏任务,找到 setTimeout,执行输出 setTimeout;

https://github.com/aooy/blog/issues/5