JavaScript 单线程模型
理解 JavaScript 单线程、事件循环和任务队列
问题
解释 JavaScript 的单线程模型,以及它如何处理异步操作。
解答
什么是单线程
JavaScript 只有一个主线程执行代码,同一时间只能做一件事。
// 同步代码按顺序执行
console.log('1');
console.log('2');
console.log('3');
// 输出: 1, 2, 3
为什么是单线程
JavaScript 最初设计用于操作 DOM。如果多线程同时修改 DOM,会产生竞态条件:
// 假设多线程场景(实际不存在)
// 线程1: document.getElementById('app').remove()
// 线程2: document.getElementById('app').innerHTML = 'hello'
// 结果不可预测
事件循环(Event Loop)
单线程通过事件循环处理异步操作:
console.log('1'); // 同步,立即执行
setTimeout(() => {
console.log('2'); // 宏任务,放入宏任务队列
}, 0);
Promise.resolve().then(() => {
console.log('3'); // 微任务,放入微任务队列
});
console.log('4'); // 同步,立即执行
// 输出顺序: 1, 4, 3, 2
执行顺序
// 完整示例
console.log('script start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(() => {
console.log('promise1');
})
.then(() => {
console.log('promise2');
});
console.log('script end');
// 输出:
// script start
// script end
// promise1
// promise2
// setTimeout
宏任务与微任务
// 宏任务: setTimeout, setInterval, I/O, UI rendering
// 微任务: Promise.then, MutationObserver, queueMicrotask
setTimeout(() => console.log('宏任务1'), 0);
setTimeout(() => console.log('宏任务2'), 0);
Promise.resolve().then(() => console.log('微任务1'));
Promise.resolve().then(() => console.log('微任务2'));
// 输出:
// 微任务1
// 微任务2
// 宏任务1
// 宏任务2
事件循环流程图
┌───────────────────────────┐
│ 调用栈 (Call Stack) │
└───────────────────────────┘
↓ 执行完毕
┌───────────────────────────┐
│ 微任务队列 (全部执行) │ ← Promise.then, queueMicrotask
└───────────────────────────┘
↓ 清空后
┌───────────────────────────┐
│ 宏任务队列 (取一个) │ ← setTimeout, setInterval
└───────────────────────────┘
↓ 执行完毕
重复循环
async/await 的执行顺序
async function async1() {
console.log('async1 start');
await async2(); // await 后面的代码相当于放入微任务队列
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
async1();
console.log('script end');
// 输出:
// script start
// async1 start
// async2
// script end
// async1 end
关键点
- 单线程原因:避免多线程操作 DOM 产生竞态条件
- 事件循环:调用栈 → 微任务队列(清空)→ 宏任务队列(取一个)→ 循环
- 微任务优先:每次宏任务执行完,先清空所有微任务
- 宏任务:setTimeout、setInterval、I/O
- 微任务:Promise.then、queueMicrotask、MutationObserver
目录