event loop它的执行顺序:
- 一开始整个脚本作为一个宏任务执行
- 执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列
- 当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完
- 执行浏览器UI线程的渲染工作
- 检查是否有
Web Worker
任务,有则执行 - 执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空
微任务包括:
MutationObserver
、Promise.then()或catch()
、Promise为基础开发的其它技术,比如fetch API
、V8
的垃圾回收过程、Node独有的process.nextTick
宏任务包括:
script
、setTimeout
、setInterval
、setImmediate
、I/O
、UI rendering
注意⚠️:在所有任务开始的时候,由于宏任务中包括了
script
,所以浏览器会先执行一个宏任务,在这个过程中你看到的延迟任务(例如setTimeout
)将被放到下一轮宏任务中来执行
题目1 执行完宏任务检查微任务
const promise = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
console.log("timerStart");
resolve("success");
console.log("timerEnd");
}, 0);
console.log(2);
});
promise.then((res) => {
console.log(res);
});
console.log(4);
// 1,2,4,timerStart,timerEnd,success
- 一开始整个脚本作为一个宏任务执行
- 先遇到
new Promise
,执行该构造函数中的代码打印1 遇到setTimeout放入下一轮红任务 打印2- 遇到promise.then()因为为pending状态,放入微任务暂不执行
- 遇到同步代码console 打印4 执行完最外层宏任务检查微任务promise结果还是pending不执行留到下一轮宏任务
- 执行第二个宏任务setTimeout打印timerStart 把promise状态改为resolve 执行同步代码打印timerEnd
- 执行完宏任务检查微任务 发现promise状态为resolve执行该微任务 打印success
题目2 宏任务先后顺序
const promise1 = new Promise((resolve, reject) => {
const timer1 = setTimeout(() => {
resolve("success");
console.log("timer1");
}, 1000);
console.log("promise1里的内容");
});
const promise2 = promise1.then(() => {
console.log('123');
});
console.log("promise1", promise1);
console.log("promise2", promise2);
const timer2 = setTimeout(() => {
console.log("timer2");
console.log("promise1", promise1);
console.log("promise2", promise2);
}, 10);
//promise1里的内容
//promise1 Promise { <pending> }
//promise2 Promise { <pending> }
//timer2
//promise1 Promise { <pending> }
//promise2 Promise { <pending> }
//timer1
//123
- 一开始整个脚本作为一个宏任务执行
- 执行呢哇new promise 遇到setTimeout放入宏任务 执行同步代码console打印 promise1里的内容
- 遇到promise2 由于promise1 状态为pending所以放入微任务 不执行
- 打印promise1 pending 打印promise2 pending
- 遇到setTimeout放入宏任务 执行完本轮宏任务 检查微任务 没有进入下一轮宏任务
- 由于宏任务timer1比宏任务timer2延后 所以先执行宏任务timer2 打印 timer2 promise1 pending 打印promise2 pending
- 执行完宏任务timer2 检查微任务 发现微任务promise1还是pending 则不执行 执行宏任务timer1 遇到resolve 把promise1 状态改为resolve 打印timer1
- 执行完宏任务timer1 检查微任务 发现微任务promise1状态为resolve 则执行该微任务打印 123
题目3 宏任务先后顺序
const timer1 = setTimeout(() => {
const promise1 = new Promise((resolve, reject) => {
resolve("success");
console.log("timer1");
console.log("promise1里的内容");
});
promise1.then(() => {
console.log('123');
});
}, 1000);
const timer2 = setTimeout(() => {
const promise2 = new Promise((resolve, reject) => {
const timer3 = setTimeout(()=>{
resolve("success");
console.log("timer2");
console.log("promise2里的内容");
},10)
});
promise2.then(() => {
console.log('456');
});
}, 10);
// timer2,promise2里的内容,456,timer1,promise1里的内容,123
- 一开始整个脚本作为一个宏任务执行 遇到timer1 timer2 放入宏任务 执行整个脚本宏任务
- 由于宏任务timer2比宏任务timer1时间短 先执行宏任务timer2
- 遇到new promise new promise中遇到宏任务timer3 放入宏任务 遇到promise2.then 由于promise2还是pending 不执行放入微任务执行完本轮宏任务
- 现在只剩下宏任务timer1 和timer3 然后对比timer1 和timer3 发现timer1 + timer3时间为20 而timer1时间是1000 所以执行timer2 打印timer2 打印promise2里的内容 执行完timer3宏任务检查微任务
- promise2 微任务状态为resolve 执行微任务promise2.then( ) 然后完成本轮宏任务
- 执行timer1 打印timer1 打印promise1里的内容 检查微任务 发现promise1状态为resolve打印123