介绍
浏览器将程序中的异步回调代码划分成一个个的任务进行执行,eventloop就是定义这些任务执行顺序的模型。这些任务分成宏任务Marcro task和微任务Micro task,它们用队列来保存。
宏任务和微任务
- 宏任务包括:
- setTimeout
- setInterval
- requestAnimationFrame
- I/O
- UI rendering
- 微任务包括:
- Promise
- Object.observe
- MutationObserver
eventloop的执行顺序
- 顺序执行程序代码, 同步代码立即执行。
- 宏任务和微任务依次进入它们各自的队列中。
- 程序顺序执行完毕后,将微任务压入调用栈,顺序执行完成;
如果程序再次生成微任务,将其放在微任务队列的末尾,在这个周期一起执行完。 - 清空微任务队列后,取出宏任务队列的队首压入调用栈,执行该宏任务。
- 循环执行1-4(执行宏任务中代码),直到调用栈,队列都为空。
实例
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);
代码执行顺序如下:
stack: [console], micro: [], marcro: [], output: 1
stack: [setTimeout], micro: [], marcro: [setTimeoutCb1]
stack: [Promise], micro: [Promise.then], marcro: [setTimeoutCb1], output: 4
stack: [setTimeout], micro: [Promise.then], marcro: [setTimeoutCb1, setTimeoutCb2]
stack: [console], micro: [Promise.then], marcro: [setTimeoutCb1, setTimeoutCb2], output: 7
stack: [Promise.then], micro: [], marcro: [setTimeoutCb1, setTimeoutCb2], output: 5
stack: [setTimeoutCb1], micro: [Promise.resolve().then], marcro: [,setTimeoutCb2], output: 2
stack: [Promise.resolve().then], micro: [], marcro: [setTimeoutCb2], output: 3
stack: [setTimeoutCb2], micro: [], marcro: [], output: 6
再看一个例子:
Promise.resolve().then(() => {
console.log('mm');
Promise.resolve()
.then(() => {
console.log('xx');
})
.then(() => {
console.log('yy');
});
}).then(() => {
console.log('nn');
});
首先,执行Promise.resolve(),生成一个Promise
stack: [Promise.resolve()], micro: [Promise.resolve().then], marcro: []
然后执行微任务,输出mm,添加一个新的Promise
stack: [console, Promise.resolve()], micro: [Promise.resolve().then], marcro: [], output: mm
这时,mm这部分回调执行完成,对外生成新的Promise,将新的Promise的then进入微任务队列
stack: [Promise.resolve().then(...)], micro: [Promise.resolve().then, Promise.resolve().then(...).then], marcro: []
执行微任务队列队首,输出xx,生成新的Promise,放在微任务队尾
stack: [Promise.resolve().then,], micro: [Promise.resolve().then(...).then, Promise.resolve().then(...yy).then], marcro: [], output: xx
顺序执行完剩余微队列,输出nn yy
stack: [Promise.resolve().then(...).then, Promise.resolve().then(...yy).then], micro: [], marcro: [], output: xx
输出为mm xx nn yy
参考文章:https://segmentfault.com/a/1190000016278115?utm_source=tag-newest