JavaScript,事件循环,微任务(Microtasks)和宏任务(Macrotasks)
JavaScript,事件循环,微任务(Microtasks)和宏任务(Macrotasks)
事件循环
事件循环概念非常简单:有一个无限循环,JavaScript引擎等待任务,执行它们,然后休眠,然后等待更多任务
宏任务与微任务
微任务是指在当前的JavaScript代码之后,下一个宏任务之前执行的小而快的任务。微任务通常由promise或async/await创建。
宏任务是指在微任务队列为空之后执行的较大和独立的任务。宏任务通常由事件,定时器或I/O操作创建 。
例子:
console.log('start'); // macrotask
setTimeout(() => {
console.log('timeout'); // macrotask
}, 0);
Promise.resolve().then(() => {
console.log('promise'); // microtask
});
console.log('end'); // macrotask
输出结果为:
start
end
promise
timeout
执行顺序
它们的执行顺序是这样的:
- JavaScript引擎从宏任务队列中取出一个宏任务,比如
console.log('start')
,并执行它。 - 如果执行过程中产生了微任务,比如
Promise.resolve().then()
,就把它加入到微任务队列中。 - 如果执行过程中产生了宏任务,比如
setTimeout()
,就把它加入到宏任务队列中。 - 当当前的宏任务执行完毕后,JavaScript引擎会检查微任务队列,如果不为空,就依次取出并执行所有的微任务,直到清空为止。
- 当微任务队列清空后,JavaScript引擎会检查宏任务队列,如果不为空,就重复步骤1。
他们的规律是:每个宏任务之前,都要执行完所有的微任务。这样可以保证微任务能够及时地响应和更新应用的状态。
有些时候,执行的顺序在不同浏览器中会有差异,可以看一下我在知乎的上回答:
为什么这段代码在Chrome环境中不符合事件循环机制? https://www.zhihu.com/question/619560968/answer/3187177238
宏微判断方法
判断任务是宏任务还是微任务的方法是:
- 如果任务是由事件,定时器,或I/O操作创建的,那么它是一个宏任务。
- 如果任务是由promise或async/await创建的,那么它是一个微任务。
- 如果任务是由微任务创建的,那么它也是一个微任务。
- 如果任务是由宏任务创建的,那么它也是一个宏任务。
参考
评论