宏任务

由宿主发起的任务称为宏观任务。 例如setTimeout函数创建的就是宏任务,当前的脚本执行也是宏任务。

1
2
3
setTimeout(()=>{
    console.log("Hello");
},100);

微任务

由JavaScript引擎发起的任务称为微任务。 微任务的主要来源是Promise。 在JavaScript的事件循环中,当期宏任务执行完或者如果调用栈为空的时候,会检查微任务队列,如果队列不为空,会执行微任务队列中的任务。

1
2
3
4
5
6
7
8
9
function createPromise(value){
    new Promise((resolve,reject)=>{
        if(value===1){
            resolve();
        }else{
            reject();
        }
    });
}

宏任务和微任务的结合的例子

以下是一个宏任务和微任务结合的例子。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function sleep(time){
    return new Promise((resolve,reject)=>{
        console.log("b");
        setTimeout(()=>{
            console.log("c");
        },time);
    })
}
sleep(10).then(()=>{
    console.log("d");
});
console.log("a");

在浏览器中,这个脚本的输出将会是b,a,d,c。 首先脚本执行的过程本身就是一个宏任务,执行到sleep的时候,进入到创建Promise的代码,这个时候输出a,遇到setTimeout会创建一个宏任务,并把回调放入宏任务队列中。执行到sleep(10).then的时候,会创建一个微任务。最后等到执行到console.log("a"),即脚本的最后一行的时候,当前脚本的宏任务就结束了,这个时候微任务队列不是空的,就会执行微任务队列中的任务。等到微任务队列为空的时候,又会执行下一个宏任务,即使用setTimeout创建的那个宏任务。

宏任务和微任务的具体执行的流程可以参考这篇文章https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/?utm_source=html5weekly。