我们都知道 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