JavaScript 事件循环与任务队列
代码示例
javascript
const pro = new Promise((resolve, reject) => {
const innerpro = new Promise((r, reject) => {
setTimeout(() => {
r(1); // 宏任务,最后执行
});
console.log(2); // 同步任务,立即执行
r(3); // 同步解析 innerpro
});
resolve(4); // 同步解析 pro
innerpro.then((res) => console.log(res)); // 微任务,排队等待
console.log('yideng'); // 同步任务,立即执行
})
pro.then((res) => console.log(res)); // 微任务,排队等待
console.log('end'); // 同步任务,立即执行执行顺序分析
1. 同步任务(立即执行)
console.log(2) → 输出: 2
console.log('yideng') → 输出: yideng
console.log('end') → 输出: end2. 微任务(同步任务完成后执行)
innerpro.then((res) => console.log(res)) → 输出: 3
pro.then((res) => console.log(res)) → 输出: 43. 宏任务(微任务完成后执行)
setTimeout中的 r(1) → 无效(innerpro 已被解析为 3)最终输出结果
2
yideng
end
3
4核心知识点
Promise 解析规则
- Promise 的
resolve/reject调用是同步的 .then()回调是异步的(微任务)- Promise 只能被解析一次,后续的解析调用会被忽略
事件循环机制
- 同步任务:在主线程上立即执行
- 微任务(Microtask):在当前宏任务结束后、下一个宏任务开始前执行
- Promise.then/catch/finally
- MutationObserver
- queueMicrotask
- 宏任务(Macrotask):在微任务队列清空后执行
- setTimeout/setInterval
- setImmediate(Node.js)
- I/O操作
- UI渲染
执行顺序总结
同步代码 → 清空微任务队列 → 执行一个宏任务 → 清空微任务队列 → 执行下一个宏任务 → ...关键要点
innerpro在同步代码中被r(3)解析,状态变为 fulfilledsetTimeout中的r(1)虽然执行了,但因为 Promise 已经是 fulfilled 状态,所以这次解析无效- 微任务的执行顺序与注册顺序一致:先注册
innerpro.then,后注册pro.then - 所有微任务执行完毕后,才会执行宏任务队列中的任务