宏任务和微任务

155 阅读2分钟

说到宏任务和微任务,就不得不说说js的执行机制。

首先,javascript是单线程运行的,在执行代码的时候,通过不同函数的执行上下文压入执行栈来保证代码的有序执行。在执行同步代码的时候,如果遇到了异步事件,javascript引擎不会一直等待其返回结果,而是会将事件挂起,继续执行执行栈中的其他任务。当同步代码执行完之后,再将异步事件对应的回加到当前执行栈中的另一个任务队列中等待执行。任务队列可以分为宏任务队列和微任务队列,当当前执行栈的事件执行完毕后,javascript引擎首先会判断微任务队列中是否有任务可以执行,如果有就将微任务队首的事件押入栈中执行。当微任务队列中的任务都执行完成后再去判断宏任务队列中的任务。

js区分宏任务和微任务有以下几点:

宏任务:
script,setTimeout,setInterval,异步ajax请求...
微任务:
原生Promise的.then()、.catch()、.finally()方法,process.nextTick

image.png

执行顺序:

可以将整个script看成看成是一个宏任务,先执行宏任务,再检查有没有微任务,如果有就执行微任务,然后渲染dom,最后进入下一次事件循环。
关于宏任务与微任务的执行顺序,也有人会说先执行微任务,再执行宏任务,这是因为宏任务是下一个事件循环开始的宏任务,而微任务是这次事件循环就执行的微任务,他们之间隔了一个dom渲染。所以造成了微任务比宏任务更快执行的错觉。

image.png

模拟场景:

去银行办业务的场景(模拟任务场景)

① 小云和小腾去银行办业务。首先,需要取号之后进行排队
⚫ 宏任务队列
② 假设当前银行网点只有一个柜员,小云在办理存款业务时,小腾只能等待
⚫ 单线程,宏任务按次序执行
③ 小云办完存款业务后,柜员询问他是否还想办理其它业务?
⚫ 当前宏任务执行完,检查是否有微任务
④ 小云告诉柜员:想要买理财产品、再办个信用卡、最后再兑换点马年纪念币?
⚫ 执行微任务,后续宏任务被推迟
⑤ 小云离开柜台后,柜员开始为小腾办理业务
⚫ 所有微任务执行完毕,开始执行下一个宏任务

原文链接:www.jianshu.com/p/334b0e40b…

经典案例:

let foo = () => {
    console.log(1);

    setTimeout(() => {
        console.log(2);

        new Promise((resolve1, reject1) => {
            new Promise((resolve2, reject2) => {
                console.log(3);
                resolve2();
            }).then(() => {
                console.log(4);
            });
            console.log(5);
            resolve1(6);
        }).then((resolve) => {
          setTimeout( () => {
            console.log(7);
          } ,100)
          console.log(resolve)
        });
    }, 0);

    new Promise((resolve, reject) => resolve(8)).then((resolve) => console.log(resolve));
};
foo();
console.log(9);

// 1 9 8 2 3 5 4 6 7