插件窝 干货文章 JavaScript单线程和任务队列是什么

JavaScript单线程和任务队列是什么

任务 执行 队列 回调 1003    来源:    2025-04-27

JavaScript 单线程与任务队列详解

单线程模型

JavaScript 采用单线程执行模型,这意味着: - 同一时间只能执行一个任务 - 代码按顺序执行,不会出现并行执行的情况

这种设计主要是为了避免复杂的线程同步问题(如死锁、竞态条件等),简化语言实现。

任务队列(Event Loop)机制

虽然 JavaScript 是单线程的,但通过事件循环(Event Loop)任务队列机制实现了异步非阻塞的行为:

主要组成部分

  1. 调用栈(Call Stack)

    • 存储函数调用的栈结构
    • 后进先出(LIFO)原则
  2. 任务队列(Task Queue)

    • 存储待处理的异步任务回调
    • 先进先出(FIFO)原则
  3. 事件循环(Event Loop)

    • 不断检查调用栈是否为空
    • 当调用栈为空时,从任务队列取出第一个任务推入调用栈执行

任务类型

  1. 宏任务(MacroTask)

    • script 整体代码
    • setTimeout/setInterval
    • I/O 操作
    • UI 渲染
    • setImmediate(Node.js)
  2. 微任务(MicroTask)

    • Promise.then/catch/finally
    • MutationObserver
    • process.nextTick(Node.js)

执行顺序

  1. 执行当前宏任务(如 script 代码)
  2. 执行过程中产生的微任务进入微任务队列
  3. 当前宏任务执行完毕后,立即执行所有微任务
  4. 微任务执行完毕后,进行 UI 渲染(浏览器环境)
  5. 从宏任务队列取出下一个宏任务执行

示例代码分析

console.log('1. 开始');

setTimeout(() => {
  console.log('4. setTimeout 回调');
}, 0);

Promise.resolve().then(() => {
  console.log('3. Promise 回调');
});

console.log('2. 结束');

输出顺序:

1. 开始
2. 结束
3. Promise 回调
4. setTimeout 回调

为什么需要这种机制

  1. 保持响应性:即使有长时间运行的任务,浏览器也不会完全冻结
  2. 高效处理 I/O:适合网络请求等异步操作
  3. 避免阻塞:通过回调机制实现非阻塞操作

实际应用注意事项

  1. 避免长时间运行的同步任务:会阻塞 UI 更新和其他任务执行
  2. 合理使用微任务:微任务会在当前宏任务结束后立即执行
  3. 理解执行顺序:特别是嵌套 Promise 和 setTimeout 的情况

理解 JavaScript 的单线程和任务队列机制对于编写高效、无阻塞的代码至关重要。