事件循环(Event Loop)是 JavaScript 实现异步编程的核心机制,它是为了解决 JavaScript 单线程执行模型下的非阻塞操作而设计的。事件循环负责协调和调度以下任务:
JavaScript 最初设计为浏览器脚本语言,主要用于处理页面交互。采用单线程模型的主要原因是:
A[运行时环境] --> B[调用栈 Call Stack]
A --> C[任务队列 Task Queue]
A --> D[微任务队列 Microtask Queue]
A --> E[Web APIs]
B --> F[正在执行的代码]
C --> G[宏任务 setTimeout/setInterval等]
D --> H[微任务 Promise/MutationObserver等]
E --> I[浏览器提供的API DOM/AJAX等]
直接在主线程上排队执行的任务。特点:
// 同步任务示例
console.log('1'); // 立即执行
const result = expensive_computation(); // 会阻塞后续代码
console.log('2'); // 等待上面的计算完成才执行
不进入主线程,而是进入任务队列的任务。分为宏任务(Macrotask)和微任务(Microtask)。
由宿主环境(浏览器、Node.js)提供的异步 API。主要包括:
// 1. setTimeout/setInterval
setTimeout(() => {
console.log('延迟执行');
}, 1000);
// 2. I/O操作
fs.readFile('file.txt', (err, data) => {
console.log('文件读取完成');
});
// 3. UI渲染
requestAnimationFrame(() => {
updateUI();
});
// 4. setImmediate(Node.js特有)
setImmediate(() => {
console.log('下一轮事件循环执行');
});
由 JavaScript 引擎提供,优先级高于宏任务。主要包括:
// 1. Promise回调
new Promise((resolve) => {
resolve('success');
}).then(result => {
console.log(result);
});
// 2. MutationObserver
const observer = new MutationObserver(() => {
console.log('DOM变化了');
});
observer.observe(document.body, { childList: true });
// 3. process.nextTick(Node.js)
process.nextTick(() => {
console.log('nextTick执行');
});
A[开始执行代码] --> B[执行同步代码]
B --> C{执行栈是否为空?}
C -->|否| B
C -->|是| D[执行所有微任务]
D --> E{微任务队列是否为空?}
E -->|否| D
E -->|是| F[执行一个宏任务]
F --> G[渲染页面]
G --> C
console.log('开始执行');
setTimeout(() => {
console.log('setTimeout 1');
Promise.resolve().then(() => {
console.log('setTimeout 1 中的 Promise');
});
}, 0);
new Promise((resolve) => {
console.log('Promise 初始化');
resolve();
}).then(() => {
console.log('Promise 第一个 then');
setTimeout(() => {
console.log('Promise 中的 setTimeout');
}, 0);
}).then(() => {
console.log('Promise 第二个 then');
});
console.log('结束执行');
/* 输出顺序:
开始执行
Promise 初始化
结束执行
Promise 第一个 then
Promise 第二个 then
setTimeout 1
setTimeout 1 中的 Promise
Promise 中的 setTimeout
*/
分析过程:
async function async1() {
console.log('async1 开始');
await async2();
console.log('async1 结束');
}
async function async2() {
console.log('async2');
}
console.log('脚本开始');
setTimeout(() => {
console.log('setTimeout');
}, 0);
async1();
new Promise(resolve => {
console.log('Promise');
resolve();
}).then(() => {
console.log('Promise.then');
});
console.log('脚本结束');
/* 输出顺序:
脚本开始
async1 开始
async2
Promise
脚本结束
async1 结束
Promise.then
setTimeout
*/
分析过程:
// Vue组件中的实际应用
export default {
data() {
return {
message: 'Hello'
}
},
methods: {
async updateMessage() {
this.message = 'Updated';
console.log(this.$el.textContent); // 仍然是 'Hello'
await this.$nextTick();
console.log(this.$el.textContent); // 现在是 'Updated'
}
}
}
// React中的优先级调度示例
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
// 低优先级更新
const timer = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
const handleClick = () => {
// 高优先级更新
ReactDOM.flushSync(() => {
setCount(0);
});
};
return (
<div onClick={handleClick}>{count}</div>
);
}
// 不推荐
setTimeout(() => {
// 处理大量数据
}, 0);
// 推荐
Promise.resolve().then(() => {
// 处理大量数据
});
// 不推荐
function processData(items) {
items.forEach(item => {
heavyComputation(item);
});
}
// 推荐
async function processData(items) {
for (let item of items) {
if (needToYield()) {
await new Promise(resolve => setTimeout(resolve, 0));
}
heavyComputation(item);
}
}
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: complexData });
worker.onmessage = function(e) {
console.log('计算结果:', e.data);
};
// worker.js
self.onmessage = function(e) {
const result = heavyComputation(e.data);
self.postMessage(result);
};
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有