宏任务
由宿主发起的任务称为宏观任务。
例如setTimeout
函数创建的就是宏任务,当前的脚本执行也是宏任务。
setTimeout(() => {
console.log("Hello");
}, 100);
微任务
由 JavaScript 引擎发起的任务称为微任务。
微任务的主要来源是Promise
。
在 JavaScript 的事件循环中,当期宏任务执行完或者如果调用栈为空的时候,会检查微任务队列,如果队列不为空,会执行微任务队列中的任务。
function createPromise(value) {
new Promise((resolve, reject) => {
if (value === 1) {
resolve();
} else {
reject();
}
});
}
宏任务和微任务的结合的例子
以下是一个宏任务和微任务结合的例子。
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。