0

0

JavaScript 事件循环:任务队列与微任务队列的执行顺序详解

碧海醫心

碧海醫心

发布时间:2025-08-17 23:02:33

|

665人浏览过

|

来源于php中文网

原创

javascript 事件循环:任务队列与微任务队列的执行顺序详解

本文深入探讨 JavaScript 事件循环中的任务队列(Task Queue)和微任务队列(Job Queue/Microtask Queue)的执行顺序。通过分析 setTimeout 和 Promise 的交互,揭示了即使微任务队列优先级更高,依赖于任务队列中任务的微任务也必须等待其依赖的任务执行完毕后才能执行。本文将通过代码示例详细解释这一过程,并提供相关注意事项,帮助开发者更好地理解 JavaScript 的异步机制。

深入理解 JavaScript 事件循环

JavaScript 是一种单线程语言,这意味着它一次只能执行一个任务。为了处理异步操作,JavaScript 使用事件循环机制。事件循环不断地检查调用栈是否为空,如果为空,则从任务队列中取出第一个任务放入调用栈中执行。

事件循环主要包含以下几个关键组成部分:

  • 调用栈(Call Stack): 用于执行同步代码。
  • 任务队列(Task Queue/Callback Queue): 用于存放异步任务的回调函数,例如 setTimeout、setInterval、事件监听器等。也称宏任务队列。
  • 微任务队列(Job Queue/Microtask Queue): 用于存放微任务的回调函数,例如 Promise.then、MutationObserver 等。
  • WebAPIs: 浏览器提供的 API,例如 setTimeout、DOM 事件等。

任务队列与微任务队列的优先级

微任务队列的优先级高于任务队列。这意味着,当调用栈为空时,事件循环会首先检查微任务队列,如果微任务队列中有任务,则会优先执行微任务队列中的所有任务,直到微任务队列为空,才会去执行任务队列中的任务。

立即学习Java免费学习笔记(深入)”;

setTimeout 与 Promise 的交互

setTimeout 的回调函数会被放入任务队列中,而 Promise.then 的回调函数会被放入微任务队列中。因此,通常情况下,Promise.then 的回调函数会比 setTimeout 的回调函数更早执行。

考虑以下代码:

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

Promise.resolve('2').then(console.log);

console.log('3');

这段代码的执行顺序如下:

Cursor
Cursor

一个新的IDE,使用AI来帮助您重构、理解、调试和编写代码。

下载
  1. setTimeout 被添加到调用栈。
  2. setTimeout 被推送到 WebAPIs,并从调用栈中弹出。
  3. Promise.resolve 被识别为异步函数,其回调函数被推入微任务队列。
  4. console.log('3') 被推入调用栈并执行,输出 3。
  5. 调用栈为空,事件循环将微任务队列中的 Promise.then 回调函数推入调用栈并执行,输出 2。
  6. 调用栈为空,事件循环将任务队列中的 setTimeout 回调函数推入调用栈并执行,输出 1。

因此,最终输出结果为 3 2 1。

依赖关系的影响

现在,考虑以下代码:

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

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

console.log('3');

这段代码的执行顺序有所不同。Promise.resolve 接收的是 setTimeout 的返回值(timeout ID),而不是 setTimeout 回调函数本身。这意味着 Promise.resolve 立即被解析,并将一个已经完成的 Promise 放入微任务队列。而 setTimeout 的回调函数仍然在任务队列中等待执行。

因此,这段代码的执行顺序如下:

  1. setTimeout 被添加到调用栈。
  2. setTimeout 被推送到 WebAPIs,并从调用栈中弹出。
  3. Promise.resolve 被识别为异步函数,其回调函数被推入微任务队列。
  4. console.log('3') 被推入调用栈并执行,输出 3。
  5. 调用栈为空,事件循环将微任务队列中的 Promise.then 回调函数推入调用栈并执行。由于 Promise 已经 resolve,所以 Promise.then 立即执行,但是它并没有输出任何东西,因为它接收的是 setTimeout 的 ID。
  6. 调用栈为空,事件循环将任务队列中的第一个 setTimeout 回调函数推入调用栈并执行,输出 1。
  7. 调用栈为空,事件循环将任务队列中的第二个 setTimeout 回调函数推入调用栈并执行,输出 2。

因此,最终输出结果为 3 1 2。

关键在于,即使 Promise.then 的回调函数在微任务队列中,但它依赖于 setTimeout 的执行结果(虽然这里只是 setTimeout 的 ID,但仍然存在依赖关系)。因此,setTimeout 必须先执行,Promise.then 才能完成。

总结与注意事项

  • JavaScript 事件循环是理解异步编程的关键。
  • 微任务队列的优先级高于任务队列。
  • 即使微任务队列优先级更高,依赖于任务队列中任务的微任务也必须等待其依赖的任务执行完毕后才能执行。
  • 在编写异步代码时,要仔细考虑任务之间的依赖关系,以确保代码按照预期的顺序执行。
  • 避免在微任务中执行耗时操作,以免阻塞事件循环。

通过理解 JavaScript 事件循环的机制,我们可以更好地编写高效、可靠的异步代码。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

398

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

525

2023.08.10

console接口是干嘛的
console接口是干嘛的

console接口是一种用于在计算机命令行或浏览器开发工具中输出信息的工具,提供了一种简单的方式来记录和查看应用程序的输出结果和调试信息。本专题为大家提供console接口相关的各种文章、以及下载和课程。

415

2023.08.08

console.log是什么
console.log是什么

console.log 是 javascript 函数,用于在浏览器控制台中输出信息,便于调试和故障排除。想了解更多console.log的相关内容,可以阅读本专题下面的文章。

510

2024.05.29

DOM是什么意思
DOM是什么意思

dom的英文全称是documentobjectmodel,表示文件对象模型,是w3c组织推荐的处理可扩展置标语言的标准编程接口;dom是html文档的内存中对象表示,它提供了使用javascript与网页交互的方式。想了解更多的相关内容,可以阅读本专题下面的文章。

3372

2024.08.14

promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

306

2023.10.12

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

406

2023.10.12

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何进行WebSocket调试
如何进行WebSocket调试

共1课时 | 0.1万人学习

TypeScript全面解读课程
TypeScript全面解读课程

共26课时 | 5.1万人学习

前端工程化(ES6模块化和webpack打包)
前端工程化(ES6模块化和webpack打包)

共24课时 | 5.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号