事件循环机制(event loop)

91 阅读2分钟

image.png

同步任务(js执行栈/回调栈) 异步任务(宏任务(宿主环境) 微任务(js引擎))

setTimeout为异步宏任务的,进任务队列排队

new promise为同步任务,进执行栈

.then .catch async(本身是同步任务)/await(await后边的都是异步的微任务)为微任务

先执行同步任务,再执行微任务异步任务,最后执行宏任务异步任务

image.png

例子:

setTimeout(() => {
    console.log("4");
    setTimeout(() => {
        console.log("8");
    }, 0);
    new Promise((r) => {
        console.log("5"); //构造函数是同步的
        r();
    }).then(() => {
        console.log("7"); //then()是异步的,这里已经入队
    });
    console.log("6");
}, 0);

new Promise((r) => {
    console.log("1"); //构造函数是同步的
    r();
}).then(() => {
    console.log("3"); //then()是异步的,这里已经入队
});

console.log("2");

输出顺序:1 2 3 4 5 6 7 8

setTimeout(function () {
    console.log('1');
});

new Promise(function (resolve) {
    console.log('2');
    resolve();
}).then(function () {
    console.log('3');
});
console.log('4');
//输出顺序:2 4 3 1
setTimeout(() => {
     new Promise(resolve => {
         resolve();
     }).then(() => {
         console.log('test');
     });

     console.log(4);
 });

 new Promise(resolve => {
     resolve();
     console.log(1)
 }).then(() => {
     console.log(3);
     Promise.resolve().then(() => {
         console.log('before timeout');
     }).then(() => {
         Promise.resolve().then(() => {
             console.log('also before timeout')
         })
     })
 })
 
 console.log(2);
 //输出:1 2 3 before timeout also before timeout 4 test

解释:

遇到setTimeout,异步宏任务,将() => {console.log(4)}放入宏任务队列中;
遇到new PromisePromise在实例化的过程中所执行的代码都是同步进行的,所以输出1;
而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中
遇到同步任务console.log(2),输出2;主线程中同步任务执行完
从微任务队列中取出任务到主线程中,输出3,此微任务中又有微任务,Promise.resolve().then(微任务a).then(微任务b),将其依次放入微任务队列中;
从微任务队列中取出任务a到主线程中,输出 before timeout;
从微任务队列中取出任务b到主线程中,任务b又注册了一个微任务c,放入微任务队列中;
从微任务队列中取出任务c到主线程中,输出 also before timeout;微任务队列为空
从宏任务队列中取出任务到主线程,此任务中注册了一个微任务d,将其放入微任务队列中,接下来遇到输出4,宏任务队列为空
从微任务队列中取出任务d到主线程 ,输出test,微任务队列为空,结束