在 JavaScript 中,代码的执行并不是完全按照书写顺序进行的。 事件循环(Event Loop)机制决定了同步代码、宏任务和微任务的实际执行顺序。理解宏任务与微任务的调度规则,有助于正确判断异步代码的执行时机。
JavaScript 的执行过程可以简化为以下几个部分:
事件循环的核心职责是: 在合适的时机,将任务队列中的任务放入调用栈执行。
宏任务是由宿主环境(如浏览器、Node.js)调度的任务,常见的宏任务包括:
setTimeout
setInterval
setImmediate(Node.js)
示例:
setTimeout(() => {
console.log('macro task');
}, 0);宏任务会进入宏任务队列,等待事件循环调度。
微任务是由 JavaScript 引擎自身调度的任务,常见的微任务包括:
Promise.then / catch / finally
queueMicrotask
MutationObserver(浏览器)
示例:
Promise.resolve().then(() => {
console.log('micro task');
});微任务会进入微任务队列,其优先级高于宏任务。
在一次完整的事件循环中,执行顺序可以概括为:
关键点在于:
每执行完一个宏任务,都会立即清空当前所有微任务。
示例代码如下:
console.log('start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('promise');
});
console.log('end');执行顺序为:
start
end
promise
setTimeout
原因是:
setTimeout 属于宏任务
微任务具有一个重要特性:
只要微任务队列不为空,就会一直执行,直到清空为止。
示例:
Promise.resolve().then(() => {
console.log(1);
Promise.resolve().then(() => {
console.log(2);
});
});输出顺序为:
1
2后创建的微任务会被追加到当前微任务队列中,并在同一轮循环中执行。
对比项 | 宏任务 | 微任务 |
|---|---|---|
调度来源 | 宿主环境 | JavaScript 引擎 |
执行优先级 | 低 | 高 |
执行时机 | 每轮事件循环取一个 | 每轮循环清空 |
常见示例 | setTimeout | Promise.then |
正确理解宏任务与微任务的执行顺序,有助于:
事件循环并不是“并发执行”,而是通过任务队列实现的有序调度机制。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。