当前位置: 首页 > news >正文

Js 主线程和异步队列哪个先执行

JavaScript 主线程与异步队列执行顺序详解

JavaScript 是单线程语言,通过事件循环(Event Loop)机制来处理同步和异步任务。以下是主线程与异步队列的执行顺序解析:

1. 执行顺序基本原则

console.log('1. 主线程同步任务');

setTimeout(() => {
  console.log('6. 宏任务队列 - setTimeout');
}, 0);

Promise.resolve().then(() => {
  console.log('4. 微任务队列 - Promise');
});

console.log('2. 主线程同步任务');

queueMicrotask(() => {
  console.log('5. 微任务队列 - queueMicrotask');
});

console.log('3. 主线程同步任务');

// 输出顺序:
// 1. 主线程同步任务
// 2. 主线程同步任务
// 3. 主线程同步任务
// 4. 微任务队列 - Promise
// 5. 微任务队列 - queueMicrotask
// 6. 宏任务队列 - setTimeout

2. 执行顺序详细机制

执行栈(Call Stack)

  • 同步代码立即执行
  • 函数调用形成栈帧

任务队列(Task Queue)

  1. 微任务队列(Microtask Queue)

    • Promise 回调(then/catch/finally)
    • queueMicrotask()
    • MutationObserver(浏览器)
    • process.nextTick(Node.js)
  2. 宏任务队列(Macrotask Queue)

    • setTimeout/setInterval
    • I/O 操作
    • UI 渲染(浏览器)
    • setImmediate(Node.js)
    • requestAnimationFrame(浏览器)

3. 完整事件循环流程

  1. 执行当前同步代码(主线程)
  2. 执行完所有同步代码后,检查微任务队列
    • 执行所有微任务(直到队列为空)
  3. 如有需要,进行UI渲染(浏览器环境)
  4. 宏任务队列取出一个任务执行
  5. 重复上述过程(事件循环)

4. 复杂示例分析

console.log('脚本开始');

setTimeout(() => {
  console.log('setTimeout1');
  Promise.resolve().then(() => {
    console.log('Promise in setTimeout1');
  });
}, 0);

setTimeout(() => {
  console.log('setTimeout2');
}, 0);

Promise.resolve().then(() => {
  console.log('Promise1');
  Promise.resolve().then(() => {
    console.log('Promise in Promise1');
  });
});

Promise.resolve().then(() => {
  console.log('Promise2');
});

console.log('脚本结束');

/* 输出顺序:
   脚本开始
   脚本结束
   Promise1
   Promise2
   Promise in Promise1
   setTimeout1
   Promise in setTimeout1
   setTimeout2
*/

5. Node.js 与浏览器的差异

环境微任务优先级宏任务优先级顺序
浏览器Promise > MutationObserver动画帧 > I/O > 定时器 > UI渲染
Node.jsprocess.nextTick > PromisesetImmediate > setTimeout/setInterval

6. 实践建议

  1. 长时间运行的微任务会阻塞渲染和宏任务执行

    // 避免这种情况
    Promise.resolve().then(() => {
      while(true) { /* 无限循环 */ }
    });
    
  2. 合理分配任务类型

    • 高优先级任务:使用微任务
    • 低优先级任务:使用宏任务
  3. 避免嵌套太深

    // 不易维护的深层嵌套
    setTimeout(() => {
      Promise.resolve().then(() => {
        setTimeout(() => {
          // ...
        }, 0);
      });
    }, 0);
    

理解这些执行顺序规则对于调试异步代码、优化性能和避免竞态条件至关重要。

http://www.dtcms.com/a/98671.html

相关文章:

  • Yolo系列之Yolov4的改进及网络框架
  • Java入门知识总结——章节(二)
  • bluecode-20240913_1_数据解码
  • 【Kafka】分布式消息队列的核心奥秘
  • 3.29前端模拟面试
  • 【区块链安全 | 第八篇】多签机制及恶意多签
  • org.apache.maven.surefire:surefire-junit-platform:jar:2.22.2 Maven打包失败
  • 逗万DareWorks|创意重构书写美学,引领新潮无界的文创革命
  • 什么是贴源库
  • unique_ptr的详细介绍
  • 量子计算与项目管理:2025年颠覆性技术将如何重构任务分解逻辑?
  • 【商城实战(103)】商城实战终章:携手共进,迈向新程
  • AI日报 - 2025年03月29日
  • 团建--树+dfs
  • MySQL的基础语法2(函数-字符串函数、数值函数、日期函数和流程函数 )
  • Linux之数据链路层
  • Vue 类与样式
  • 【数学建模】(启发式算法)模拟退火算法:原理、实现与应用
  • [c++项目]基于微服务的聊天室服务端测试
  • 基于ssm的课程辅助教学平台(全套)
  • 直流电机类型及其控制技术
  • 免费下载 | 2025年网络安全报告
  • libimobiledevice项目中各个库的作用
  • 【数据结构】二叉树的递归
  • 前端音频和视频上传预览功能的探索与总结
  • Linux 基本使用和 web 程序部署
  • 人生感悟8
  • 【测试】每日3道面试题 3/29
  • Advanced Renamer:批量文件重命名工具
  • Vue3组件事件用户信息卡练习