事件循环
宏任务:setTimeout/setImmediate
微任务:Promise
浏览器: 执行一个宏任务,执行所有微任务
node:先执行所有宏任务,再执行微任务
function test() { console.log('start') setTimeout(() => { console.log('children2') Promise.resolve().then(() => { console.log('children2-1') }) }, 0) setTimeout(() => { console.log('children3') Promise.resolve().then(() => { console.log('children3-1') }) }, 0) Promise.resolve() .then(() => { console.log('children1') }).then(() => { console.log('children1-1') }) console.log('end') } test() /** * 浏览器分析 * 执行一个宏任务,执行完所有微任务 * 1.start主线执行, * 2.children2添加到宏任务队列 * 3.children3添加到宏任务队列 * 4.children1添加到微任务队列 * 5.children1-1添加到微任务队列 * 6.end主线执行 * ------------以上主线任务执行完毕,开始检查微任务---------------- * 7.微任务队列中有children1,children1-1执行 * ------------微任务执行完毕,开始检查宏任务------------------- * 8.children2排在宏任务队列第一个,执行,并将children2-1添加到微任务中 * ------------宏任务执行一个,开始执行所有微任务--------------- * 9.微任务队列只有children2-1,执行 * ------------微任务执行完毕,开始检查宏任务------------------- * 10.宏任务队列第二个为children3,执行,并将children3-1添加到微任务中 * ------------宏任务执行一个,开始执行所有微任务--------------- * 11.微任务队列只有children3-1,执行 * ------------微任务执行完毕,开始检查宏任务,无,检查微任务,无,代码执行完毕------------------- */ /** * node11以下版本分析 * 先执行所有的宏任务,再执行微任务 * 1.start主线执行, * 2.children2添加到宏任务队列 * 3.children3添加到宏任务队列 * 4.children1添加到微任务队列 * 5.children1-1添加到微任务队列 * 6.end主线执行 * ------------以上主线任务执行完毕,开始检查微任务---------------- * 7.微任务队列中有children1,children1-1,执行 * ------------微任务执行完毕,开始检查宏任务------------------- * 8.children2排在宏任务队列第一个,执行,并将children2-1添加到微任务中 * 9.宏任务队列第二个为children3,执行,并将children3-1添加到微任务中 * ------------宏任务全部执行完毕,开始检查微任务------------------- * 10.微任务第一个children2-1,执行 * 11.微任务第二个children3-1,执行 * ------------微任务执行完毕,开始检查宏任务,无,检查微任务,无,代码执行完毕------------------- */
有async函数
async函数,看调用阶段,如
async function async() { console.log(1) } console.log(2) async() /** * async函数调用在2后面,所以先打印2再打印1 */
有await async的调用,如
async function async1() { console.log('async1 start') await async2() console.log('async1 end') } async function async2() { console.log('async2') }
可改写成promise.then便于理解
async function async1() { console.log('async1 start') new Promise(function (resolve) { console.log('async2') resolve() }).then(function () { console.log('async1 end') }) }
完整例子:
async function async1() { console.log('async1 start') await async2() console.log('async1 end') } async function async2() { console.log('async2') } console.log('script start') setTimeout(function () { console.log('setTimeOut') }, 0) async1() new Promise(function (resolve) { console.log('promise1') resolve() }).then(function () { console.log('promise2') }) console.log('script end') /** * 1、顺序执行,打印script start * 2、宏任务队列加入setTimeOut * 3、调用async1,打印async1 start * 4、调用async2,打印async2 * 5、微任务队列中加入async1 end * 6、打印promise1 * 7、微任务队列加入promise2 * 8、打印script end * -------------代码执行完毕,此时微任务队列中有async1 end,promise2,宏任务队列中有setTimeOut------------ * 9、执行所有微任务,打印async1 end,promise2 * 10、执行宏任务,打印setTimeOut * ------结果为script start->async1 start->async2->promise1->script end->async1 end->promise2->setTimeOut---------- * 因主线任务完成后宏任务队列中只有一个,所以node应该与浏览器打印结果相同(实际并不相同,node中promise2与async1 end打印顺序颠倒了,还没弄懂是怎么回事) */
console.log(1); setTimeout(() => { console.log(2) }); Promise.resolve().then(() => { console.log(3); }); setImmediate(() => { console.log(4) }); new Promise(resolve => { console.log(5); resolve(); console.log(6); }).then(() => { console.log(7) }); Promise.resolve().then(() => { console.log(8); Promise.resolve().then(() => { //这里容易产生误解,并不是又一层回调。应该在8后添加入微任务队列 console.log(9) }); }); //1 5 6 3 7 8 9 2 4