事件循环

宏任务: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
原文地址:https://www.cnblogs.com/lianglanlan/p/14420772.html