基本流程
- 调用栈(Call Stack) :调用栈是一个存放函数调用的栈结构。JavaScript 引擎会按顺序执行栈中的同步代码。
- 任务队列(Task Queue) :当遇到异步任务(例如
setTimeout、Promise等)时,这些任务不会立即执行,而是加入到任务队列中。 - 事件循环(Event Loop) :事件循环不断地检查调用栈是否为空。当栈为空时,事件循环会将任务队列中的任务放入调用栈中执行。这就使得异步任务能够在同步代码执行完毕后被执行。
任务类型
- 宏任务(Macro Task) :如
setTimeout、setInterval、I/O 任务等。每次事件循环执行时,宏任务队列中只会取一个任务放入调用栈执行。 - 微任务(Micro Task) :如
Promise.then、MutationObserver等。在宏任务执行完毕之后,事件循环会清空微任务队列中所有的任务。
执行顺序示例
javascript
复制代码
console.log("1"); // 同步代码,立即执行
setTimeout(() => {
console.log("2"); // 宏任务,延迟执行
}, 0);
Promise.resolve().then(() => {
console.log("3"); // 微任务,延迟执行,但优先级高于宏任务
});
console.log("4"); // 同步代码,立即执行
输出顺序为:1 -> 4 -> 3 -> 2
原因解析
- 1 和 4 是同步代码,立即执行。
- Promise 的
.then回调是微任务,在同步代码完成后立即执行。 - setTimeout 是宏任务,会被放入下一轮事件循环。