news 2026/4/8 14:04:09

JavaScript 事件循环机制详解及项目中的应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript 事件循环机制详解及项目中的应用

第一部分:基础概念

1. JavaScript 执行环境

JavaScript 是单线程的,这意味着它一次只能执行一个任务。为了处理异步操作,JavaScript 使用事件循环机制。

2. 核心组件

  • 调用栈(Call Stack):执行同步代码的地方
  • 任务队列(Task Queue):分为宏任务队列和微任务队列
  • 事件循环(Event Loop):协调调用栈和任务队列的机制

第二部分:举例详细解析

console.log('1. 同步任务开始');setTimeout(()=>{console.log('2. setTimeout 回调');},0);Promise.resolve().then(()=>{console.log('3. Promise.then 回调');});console.log('4. 同步任务结束');

执行步骤分析:

第1步:同步任务执行
  1. console.log('1. 同步任务开始')压入调用栈,立即执行,输出1
  2. setTimeout压入调用栈,Web API 开始计时(0ms),回调函数放入宏任务队列
  3. Promise.resolve().then()压入调用栈,.then()的回调函数放入微任务队列
  4. console.log('4. 同步任务结束')压入调用栈,立即执行,输出4

此时状态:

  • 调用栈:空
  • 微任务队列[Promise.then回调]
  • 宏任务队列[setTimeout回调]
第2步:事件循环检查
  1. 调用栈为空,事件循环开始工作
  2. 优先检查微任务队列,发现有一个任务
  3. 执行微任务:console.log('3. Promise.then 回调'),输出3
  4. 微任务队列清空
第3步:继续事件循环
  1. 微任务队列为空,现在检查宏任务队列
  2. 执行宏任务:setTimeout回调,输出2
  3. 宏任务队列清空

最终输出顺序:1 4 3 2

console.log('script start')asyncfunctionasync1(){awaitasync2()console.log('async1 end')}asyncfunctionasync2(){console.log('async2 end')}async1()setTimeout(function(){console.log('setTimeout')},0)newPromise(resolve=>{console.log('Promise')resolve()}).then(function(){console.log('Promise1')})

关键概念:async/await

  • async函数总是返回一个 Promise
  • await会暂停 async 函数的执行,直到 Promise 解决
  • await后面的代码相当于放在.then()中,属于微任务

执行步骤分析:

第1步:同步任务执行
  1. console.log('script start')→ 输出script start

  2. 定义函数async1async2(不执行)

  3. 调用async1()

    • 进入async1,遇到await async2()
    • 调用async2()console.log('async2 end')→ 输出async2 end
    • await暂停执行,console.log('async1 end')被包装成微任务放入微任务队列
  4. setTimeout→ 回调函数放入宏任务队列

  5. 执行new Promise

    • console.log('Promise')是同步代码 → 输出Promise
    • resolve()执行,.then()的回调放入微任务队列

此时状态:

  • 调用栈:空
  • 微任务队列[async1 end, Promise1](注意顺序!)
  • 宏任务队列[setTimeout回调]
第2步:事件循环检查微任务
  1. 调用栈为空,执行微任务

  2. 按入队顺序执行微任务:

    • 第一个微任务:console.log('async1 end')→ 输出async1 end
    • 第二个微任务:console.log('Promise1')→ 输出Promise1
  3. 微任务队列清空

第3步:执行宏任务
  1. 执行setTimeout回调 → 输出setTimeout

最终输出顺序:script start → async2 end → Promise → async1 end → Promise1 → setTimeout

那么到此,应该是可以理解到事件循环的感觉了,那接下来我们就开始看看事件循环的完整逻辑

1. 任务分类

宏任务(Macrotasks)
  • setTimeoutsetInterval
  • setImmediate(Node.js)
  • requestAnimationFrame(浏览器)
  • I/O 操作
  • UI 渲染(浏览器)
  • 主线程的 script 标签内容
微任务(Microtasks)
  • Promise.then().catch().finally()
  • process.nextTick()(Node.js,优先级最高)
  • MutationObserver(浏览器)
  • queueMicrotask()
  • async/await的后续代码

2. 事件循环执行顺序

1. 执行一个宏任务(script标签内容) 2. 执行过程中遇到异步任务: - 宏任务 → 放入宏任务队列 - 微任务 → 放入微任务队列 3. 当前宏任务执行完毕 4. 检查微任务队列,依次执行所有微任务 5. 如有必要,进行UI渲染 6. 从宏任务队列取出下一个宏任务执行 7. 回到步骤3,形成循环

3. 重要规则

规则1:微任务优先
  • 每执行完一个宏任务,都要清空所有微任务
  • 微任务执行期间产生的新微任务会加入当前队列,并在本次循环中执行
规则2:async/await 转化

javascript

asyncfunctionexample(){awaitfoo()// 相当于 Promise.resolve(foo()).then(...)console.log('A')// 这部分在微任务队列中}
规则3:多个任务队列
  • 宏任务可能有多个来源(定时器、I/O等),有各自的队列
  • 微任务只有一个队列,按入队顺序执行

在举例理解一下

javascript

// 测试微任务嵌套Promise.resolve().then(()=>{console.log('微任务1');Promise.resolve().then(()=>{console.log('微任务中的微任务');});}).then(()=>{console.log('微任务2');});// 输出顺序:微任务1 → 微任务中的微任务 → 微任务2

javascript

// 测试多个宏任务setTimeout(()=>console.log('宏任务1'),10);Promise.resolve().then(()=>console.log('微任务1'));setTimeout(()=>{console.log('宏任务2');Promise.resolve().then(()=>console.log('宏任务2中的微任务'));},1);Promise.resolve().then(()=>console.log('微任务2'));setTimeout(()=>{console.log('宏任务3');Promise.resolve().then(()=>console.log('宏任务3中的微任务'));},0);结果: 微任务1微任务2宏任务3宏任务3中的微任务 宏任务1宏任务2宏任务2中的微任务 为什么呢?聪明的你已经会了 一开始 微任务 放入 微任务1, 微任务2;然后宏任务放入 宏任务3这个时候, 计时器还没有到底100ms的时候, 打印微任务1、微任务2;然后微任务清空,开始 宏任务3, 放入微任务 宏任务3中的微任务,然后打印宏任务3中的微任务; 然后计时器到了,打印宏任务1、宏任务2、放入微任务, 打印宏任务2中的微任务;大概就是这种感觉

总结

  1. 同步任务立即执行
  2. 微任务宏任务优先级高
  3. 每个宏任务执行后,都要清空所有微任务
  4. async/await本质是 Promise 的语法糖,await后面的代码是微任务
  5. 事件循环确保了 JavaScript 的单线程能够处理异步操作
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/30 10:00:51

人工智能领域重大突破:新型模型架构引领行业变革

人工智能领域重大突破:新型模型架构引领行业变革 【免费下载链接】ERNIE-4.5-0.3B-Base-PT 项目地址: https://ai.gitcode.com/hf_mirrors/baidu/ERNIE-4.5-0.3B-Base-PT 在当今科技飞速发展的时代,人工智能技术正以前所未有的速度改变着我们的生…

作者头像 李华
网站建设 2026/4/3 23:36:40

[CTF]攻防世界:easy_laravel 学习

题目:攻防世界:easy_laravel 学习提示:blade pop chain(代码审计sql注入blade缓存反序列化)直接F12查看源码php的web框架一、注入 查看源码: 这里应该是注入点:看到管理员认证,判断…

作者头像 李华
网站建设 2026/4/8 12:28:43

DDNS动态域名解析方案对比与实战配置

本文详解DDNS工作原理、主流方案对比,以及在各种场景下的实战配置。前言 家里的宽带IP是动态的,每次重启光猫IP就变了。想从外面访问家里的服务器,怎么办? DDNS(Dynamic DNS) 就是解决这个问题的&#xff1…

作者头像 李华
网站建设 2026/4/6 19:37:33

28、地理数据剖析:基于关联数据的位置与用户画像构建

地理数据剖析:基于关联数据的位置与用户画像构建 1. 引言 在当今数字化时代,数据的价值愈发凸显,尤其是地理相关的数据。通过对基站(BTS)使用情况以及用户行为数据的分析,可以构建精准的地理画像和用户画像,为商业决策、地理营销等领域提供有力支持。本文将深入探讨基…

作者头像 李华
网站建设 2026/4/7 16:59:18

人工智能大模型技术突破:Qwen3-30B-A3B-MLX-8bit模型引领行业新变革

人工智能大模型技术突破:Qwen3-30B-A3B-MLX-8bit模型引领行业新变革 【免费下载链接】Qwen3-30B-A3B-MLX-8bit 项目地址: https://ai.gitcode.com/hf_mirrors/Qwen/Qwen3-30B-A3B-MLX-8bit 在当今数字化浪潮席卷全球的时代,人工智能技术正以前所…

作者头像 李华
网站建设 2026/4/8 6:36:28

开发一个应用程序的架构有哪些?它们的工作原理和机制概述

现代软件开发有多种架构模式,每种都有其特定的工作原理、机制和核心技术。下面我将详细论述几种主要的应用程序架构,并给出实例说明。 一、单体架构(Monolithic Architecture) 工作原理和机制 单体架构将所有功能模块(…

作者头像 李华