一、概述
- 执行栈:放置需要执行的同步任务
- 任务队列
- 宏任务(task):
<script>
标签的整体代码、setTimeout
、setInterval
、setImmediate
、I/O、UI渲染 - 微任务(micro-task):
Promise的resolve、reject
,await
、process.nextTick
、Object.observe
、MutationObserver
- 宏任务(task):
- 事件循环(event-roop)
- 从宏任务队列中取第一个任务,丢入执行栈中
- 执行完执行栈中的所有任务(期间有宏任务或微任务生成时,放入相应队列尾部)
- 若微任务队列不为空,将微任务队列中的任务按顺序丢入执行栈中。微任务队列为空时跳到第5步
- 执行完执行栈中的所有任务(期间有宏任务生成,放入宏任务队列尾部;有微任务生成时,微任务放到执行栈尾部等待执行)
- 若宏任务队列不为空,返回第1步
- node.js 事件循环:
- node11 之后,其事件循环机制与浏览器对齐。
- node10 之前,node使用的是自己的一套事件循环机制,与浏览器事件循环存在很大差异。
二、注意
-
promise
的then
依赖于前一个resolve
;且若前边没有resolve
则 promise 一直处于pendding
状态,then
一直无法执行; -
微任务队列中若是碰到
then
,则把then
后边的微任务丢到当前微任务队列的末尾,而不是立即执行// 例如对于下边的微任务队列 /*micro 1*/ console.log(1); /*micro 2*/ .then{ console.log(2) } /*micro 3*/ .then{ console.log(3) .then{ console.log(4) } } /*micro 4*/ .then{ console.log(5) } /*micro 5*/ console.log(6) // 结果: 1 6 2 3 5 4
-
await
后边的内容相当于new Promise
,await
的下一行及之后的代码相当于then
三、例题
-
示例1
console.log('1'); setTimeout(function() { console.log('2'); process.nextTick(function() { console.log('3'); }) new Promise(function(resolve) { console.log('4'); resolve(); }).then(function() { console.log('5') }) }) process.nextTick(function() { console.log('6'); }) new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8') }) setTimeout(function() { console.log('9'); process.nextTick(function() { console.log('10'); }) new Promise(function(resolve) { console.log('11'); resolve(); }).then(function() { console.log('12') }) })
执行结果: 1, 7, 6, 8, 2, 4, 3, 5, 9, 11, 10, 12
-
示例2
async function a() { console.log('a') await b() console.log('a end') } async function b() { console.log('b') } a() setTimeout(function () { console.log('setTimeout') }, 0) new Promise(function (resolve, reject) { console.log('promise') resolve() }).then(function () { console.log('then') }) console.log('main end')
执行结果: a, b, promise, main end, a end, then, setTimeout
-
示例3
setTimeout(function () { console.log('8') }, 0) async function async1() { console.log('1') const data = await async2() console.log('6') return data } async function async2() { return new Promise(resolve => { console.log('2') resolve('async2的结果') }).then(data => { console.log('4') return data }) } async1().then(data => { console.log('7') console.log(data) }) new Promise(function (resolve) { console.log('3') resolve() }).then(function () { console.log('5') })
执行结果: 1, 2, 3, 4, 5, 6, 7, async的结果, 8