【走进浏览器】之Event Loop的那些事

Agent Runtime 正在成为 AI 时代的操作系统内核 Agent runtime 不是新概念,而是 AI 工程化演进中必然出现的基础设施层——它将模型执行、状态管理、安全凭证、可观测性等能力从应用逻辑中剥离,抽象为可标准化、可替换、可审计的底层服务。其核心原理在于‘会话即事件日志’:通过结构化、持久化、带因果链的 event stream 替代脆弱的 prompt context,解决上下文截断、状态不一致、调试不可追溯等生产级痛点。这一设计直接支撑金融风控、合规审计、跨系统协同等高要求场景,并推动 runtime 层走向 commoditization。当前 阅读详情

走进 Event Loop

大家都知道,在使用 setTimeout 或是其他异步任务的时候要多加小心,这是因为其涉及到了 Js 的事件循环机制。很多时候因为经验,我们不需要知道其原理就能避免一些错误,但今天我们还是来聊一聊,浏览器下的EventLoop机制的那些事~

在这里插入图片描述

一、JavaScript 与单线程?

JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么 JavaScript 不能有多个线程呢?这样能提高效率啊。

答:

JavaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定 JavaScript 同时有两个线程,一个线程在某个 DOM 节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

所以,为了避免复杂性,从一诞生,JavaScript 就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

二、任务

简单了解一下同步和异步这两个概念

2.1 同步与异步

一般而言,任务分为:发出调用和得到结果两步。

  • 发出调用,“立即”得到结果是为同步
  • 发出调用,但无法“立即”得到结果,需要额外的操作才能得到预期的结果是为异步。

同步任务需要就是调用之后一直等待,直到返回结果。异步则是调用之后,不能直接拿到结果,通过一系列的手段才最终拿到结果(调用之后,拿到结果中间的时间可以介入其他任务)。

来阅读下面的代码:

console.log(1);

setTimeout(() => {
  console.log(2);
}, 1000);

console.log(3);

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

console.log(5);

拟人分析:

  1. 我要喝水 1:拿起水,喝~
  2. 我订了个午餐 2:上面预计送达时间 1 分钟,我当然不可能坐等外卖!
  3. 我订要喝水 3:拿起水,喝~
  4. 我定了个水果 4:上面预计送达时间 0,但只要是外卖,我就不着急!
  5. 订完外卖,我直接喝水 5:嗝~,不能再喝了,该谢谢了
  6. 此时我正好没事做,不如去看看外卖?
  7. 果然预计时间 0s 送达的水果先到了,我先吃口水果
  8. 吃完水果午餐也到了,嗯,愉快的一天

需要注意的是:我们这样对待setTimeout(订外卖),是因为我们不知道要等多久,所以我们完全不关心他是不是马上送到,而是将眼前的任务(手里看得见的其他事情)执行完,当手里没事做时才会去执行setTimeout指定的回调函数(取外卖)。

这段分析合情合理,我感觉我离真相又进了一步!

2.2 宏任务与微任务

下面的两种任务,都属于异步任务,但浏览器对他们的处理存在很大的区别。

  • 宏任务:MacroTask
    • 如:setTimeout、setInterval、script(整体代码)、 I/O 操作、UI 渲染等。
  • 微任务:MicroTask
    • 如: new Promise().then(回调)、MutationObserver(html5 新特性) 等。

三、EventLoop

js 的另一大特点是非阻塞,借用书中的一句话:这需要一套机制来处理现在运行的事情和将来要运行的事情,而 EventLoop 就是这样一套机制。

3.1 执行栈

JS 执行栈采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空。

3.2 对同步、异步的处理

Javascript 单线程任务被分为同步任务和异步任务,同步任务会在调用栈中按照顺序等待主线程依次执行,异步任务会在异步任务有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。

在这里插入图片描述

注意

  • 宏任务队列可以有多个;
  • 微任务队列只有一个;

3.3 EventLoop 过程解析

上图:

在这里插入图片描述

值得一提的是,整个<script>标签包裹的整体代码,是属于宏任务。

  1. 任务会依次进入执行栈,而首先入场的就是——宏任务全局上下文(script);
  2. 执行同步任务;
  3. js 引擎遇到一个异步任务后并不会一直等待其返回结果:
    • 遇到异步任务,交给异步处理模块处理,对应的异步处理线程处理异步任务需要的操作,例如定时器的计数和异步请求监听状态的变更;
    • 当异步事件返回结果后,事件触发线程将回调函数(标记)加入任务队列,等待栈为空时,依次进入栈中执行;
  4. 执行栈在执行完同步任务后,查看执行栈是否为空,如果执行栈为空:
    • 先检查微任务(microTask)队列,如果存在任务,则一次性执行完所有微任务,无任务则跳过
    • 后检查宏任务(macroTask)队列,如果存在任务,则取出第一个宏任务,执行,

总结 1:

每次单个宏任务执行完毕后,检查微任务(microTask)队列是否为空,如果不为空的话,会按照先入先出的规则全部执行完微任务(microTask)后,设置微任务(microTask)队列为 null,然后再执行宏任务,如此循环。

总结 2:

又因为第一次进入执行栈的总是宏任务(Script),而每次宏任务完成后,都会读取微任务队列,所以,大家也会听见另一种表述方式:、

每一轮循环中,同步任务执行后会在末尾执行并清空所有的微任务,会在下一轮循环中取第一个宏任务执行,如此循环。

下面我们用两段代码来分析一下今天所学~

在这里插入图片描述

四、示例分析

4.1 同步+宏任务

console.log("1");
// 0s延迟的定时任务
setTimeout(function timeout() {
  console.log("2");
}, 1000);
setTimeout(function timeout() {
  console.log("3");
}, 0);
console.log("4");

以这段代码举例,我们按照第三小节的步骤逐步分析:

  1. 从全局任务入口,首先打印日志 1,
  2. 遇到宏任务setTimeout-log(2),交给异步处理模块
  3. 遇到宏任务setTimeout-log(3),交给异步处理模块
  4. 顺序执行,打印日志 4,
  5. 同步任务执行完毕,读取微任务队列,为 null,则读取宏任务队列第一个,先返回处理结果的是setTimeout-log(3),将 log(3) 内回调函数加入执行队列,顺序执行,打印日志 3,
  6. 继续重复步骤 5,顺序执行,打印日志 2,执行结束。

注意:

读取宏任务队列的任务,setTimeout-log(3),虽然定时器的等待时间被设置 0 秒,但是W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为 4ms。

由于浏览器在执行以上三步时,并未耗时很久,所以当宏任务setTimeout-log(3)1 执行完时, setTimeout-log(1)的等待时间并未结束,所以在 1 秒后打印,实际上并未等待 1 秒。

4.2 同步+宏任务+微任务

再来看下面的代码:

setTimeout(function() {
  console.log(1);

  Promise.resolve().then(function() {
    console.log(2);
  });
}, 0);

setTimeout(function() {
  console.log(3);
}, 0);

Promise.resolve().then(function() {
  console.log(4);
});

console.log(5);

第一轮循环

  1. 同样从全局任务入口,遇到宏任务setTimeout-log(1),交给异步处理模块,由于等待时间为 0,直接加入宏任务队列。
  2. 再次遇到宏任务setTimeout-log(3),交给异步处理模块,同样直接加入宏任务队列。
  3. 遇到微任务then()-log(4),加入微任务队列。
  4. 最后遇到打印语句,直接打印5。
  5. 执行栈空

画出当前任务队列的情况:

第二轮循环

  1. 执行栈空后,读取微任务队列,执行then()-log(4),打印4,微任务队列为null;

画出此刻任务队列的情况:

  1. 微任务队列为空,读取宏任务队列的最靠前的任务setTimeout-log(1);;
  2. 打印1,又遇到微任务then()-log(2),加入微任务队列。第二轮循环结束。

画出当前任务队列的情况:

第三轮循环

  1. 读取微任务队列:then()-log(2),打印2,微任务队列为null
  2. 读取宏任务队列首个任务:setTimeout()-log(3),打印3

至此,异步任务队列也被清空,整个任务执行完毕

最终结果:5,4,1,2,3

五、写在最后

尝试走进浏览器的大门,你会对自己天天要调试的页面(浏览器)变得越来越亲切,也许有一天你会深耕在浏览器领域,希望而这一切的起因都是因为这个浏览器系列,来自《余光前端笔记》

5.1 本文参考

5.2 关于我

关于我

  • 花名:余光
  • WX:j565017805
  • 邮箱:webbj97@163.com

其他沉淀

]

Pyppeteer:基于Chrome DevTools的Python自动化与爬虫利器 在Python自动化与数据抓取领域,浏览器自动化是处理动态网页内容的核心技术。其原理是通过程序控制浏览器,模拟真实用户操作,从而实现对JavaScript渲染页面的交互与数据提取。这项技术的价值在于能够高效、精准地完成自动化测试、数据采集和网页监控等任务。Pyppeteer作为Puppeteer的Python版本,直接通过Chrome DevTools协议与Chromium通信,提供了比传统工具更精细的控制和更快的执行速度。它特别适用于需要处理单页应用、进行网络请求拦截或生成网页报告的工程实践场景。对于面临 阅读详情

相关推荐

Managed Agents:企业级 AI Agent 运行时的可靠性革命

AI Agent 运行时(Runtime)是支撑智能体稳定、安全、可审计执行的核心基础设施,其本质是状态管理、工具调度与沙箱隔离的技术集合。随着 Anthropic 等厂商推出托管型 Agent Runtime,行业正从‘模型即能力’转向‘运行即服务’——通过会话事件日志化、Harness 无状态化、沙箱牲畜化三大设计,系统性解决上下文溢出、凭证泄露、故障不可追溯等工程顽疾。该范式显著提升 agent 在金融、医疗、客服等高合规场景的落地可行性,并推动可观测性(Trace)、治理策略(Governance)

frank1998819 436

事件循环机制EventLoop

https://www.jianshu.com/p/c3716bedfaae 事件循环机制EventLoop BigTooth_3611关注 0.3372019.01.28 09:04:23字数 3,035阅读 1,677 Event Loop即事件循环,是解决javaScript单线程运行阻塞的一种机制。 一、EventLoop的相关概念 1、堆(Heap) 堆表示一大块非结构化的内存区域,对象,数据被存放在堆中 2、栈(Stack) 栈在javascript中又称执行栈,调用栈,是一种后进先出的数组结构

叶子先生的博客 8190

深入理解 Event Loop事件循环机制

Event Loop事件循环机制 事件循环机制(Event Loop)是全面了解javascript代码执行顺序绕不开的一个重要知识点。 为什么会有事件循环机制? javascript从诞生之日起就是一门单线程的非阻塞的脚本语言。这是由其最初的用途来决定的:与浏览器交互。 首先等来了解js为什么是单线程的吧! 首先要明白线程的概念? 进程是资源分配的最小单位,线程是进程的一部分,是cpu调度的基本单位; 了解浏览器 浏览器中,每次打开一个tab页面,其实就是新开了一个进程,在这个进程中,还有js引擎线程、ui渲染线程、http请求线程。 这里面还可深入了解js引擎线程、ui渲染线程、http请

EventLoop 事件循环机制

Event Loop 在JavaScript中,任务被分为两种,一种宏任务(MacroTask)也叫Task,一种叫微任务(MicroTask)。

Dark_programmer的博客 7486

【实用运维脚本】Windows 批量 TCP 端口检测(tcping 一键巡检)

摘要:本文介绍一款高效的Windows批量TCP端口检测脚本,适配tcpingv0.39工具,实现多服务器一键巡检。脚本具有进度可视化、双日志输出、自动容错等优势,支持注释行过滤和UTF-8编码。 使用仅需三步: 1)下载tcping工具 2)编辑目标列表 3)运行脚本即可自动检测并生成带编号的检测报告。 该方案解决了手动检测效率低、易遗漏的问题,特别适合日常运维中的端口连通性检查,实测稳定可靠,开箱即用。

蕲士|D365 & 服务器运维,心有东坡,行稳致远。 797

ADS1220 STM32硬件SPI驱动程序

前一段时间温故了下标准库,使用的是F1系列芯片,测试程序。

随风飘零翼的博客 5762

event loop 详解

带你轻轻松松搞懂 event loop。

qq_61233877的博客 1万+

利用VBA宏实现LightTools仿真数据自动化导出至Excel

本文详细介绍了如何利用VBA宏实现LightTools仿真数据自动化导出至Excel的完整流程。通过调用LTAPI接口,工程师可以自动执行仿真、抓取照度与光强等数值数据、捕获并粘贴仿真图像,从而将重复性工作自动化,显著提升光学设计工作的效率和准确性。

weixin_28314575的博客 496

一文读懂什么是Event Loop

本文将深入介绍Event Loop的工作原理、任务分类以及应用场景,帮助读者更加全面深入地了解这个概念。

杨树林er的博客 4040

直流有刷电机控制 - 认识电机(一)

电机控制学习

u011030644的博客 916

2026款拯救者Y9000P深度学习环境配置指南

这套环境适配 2026 款拯救者 Y9000P 的 RTX5060,可直接用于 CV(图像分类、检测)、NLP 等 PyTorch 深度学习任务,GPU 利用率正常,无兼容性问题。后续复现环境时,直接按本文步骤操作即可~

大糊涂虫 2633

【js进阶】全面理解Event Loop这一篇就够了

文章目录一、前言 一、前言 event loops隐藏得比较深,很多人对它很陌生。但提起异步,相信每个人都知道。异步背后的“靠山”就是event loops。这里的异步准确的说应该叫浏览器的event loops或者说是javaScript运行环境的event loops,因为ECMAScript中没有event loops,event loops是在HTML Standard定义的。 ...

goodloving的博客 1万+

从入门到精通:3D视觉与SLAM实战全流程 mastery 教程

本文系统介绍了3D视觉与SLAM技术的应用前景、核心技术和实战路径。3D视觉通过RGB-D相机、激光雷达等传感器获取环境三维信息,SLAM技术实现自主定位与地图构建,二者结合广泛应用于自动驾驶、机器人导航等领域。文章详细拆解了点云处理、视觉里程计、回环检测等关键技术,并提供了ORB-SLAM2算法复现、语义SLAM开发的实战教程,涵盖硬件选型、环境配置到代码实现全流程。最后规划了从入门到专家的学习路径,推荐了相关书籍、开源项目和数据集资源,为读者掌握这一前沿技术提供了完整指南。

m0_71589036的博客 133

一篇文章带你走进面试常考点-Promise

JavaScript是一个单线程的语言,因此它并不能像Java一样并发地执行2多个任务。只能一个接一个地按照JavaScript规定好的顺序去执行。但我们都知道的是有些程序(定时器、AJAX请求等)是需要一定时间等待后才能执行的,当我们将需要耗时的代码块写在不需要耗时的代码块前时,会产生阻塞,为了避免这种情况的发生JavaScript背后有一套属于自己的执行机制。

Kousii的博客 963

基于深度学习的柠檬等级检测系统 —— YOLOv8 + UI界面 + 数据集

本项目的目标是构建一个柠檬等级检测系统,通过深度学习模型自动检测柠檬的等级。自动检测柠檬等级:通过图像中的柠檬特征,自动判断其成熟度和质量。实时视频检测:通过摄像头实时监控柠檬的质量等级。用户友好的UI界面:为用户提供简洁直观的操作界面,支持图像上传、实时视频检测等功能。本项目展示了如何基于YOLOv8模型开发一个柠檬等级检测系统,结合PyQt5实现了用户友好的UI界面。通过该系统,用户可以快速上传柠檬图像并自动识别其等级,极大提升了检测效率和准确性。数据集的扩展。

YOLO 1111

基于simulink的车道保持辅助系统(LKA)的仿真与实现

本文介绍了如何利用Simulink实现车道保持辅助系统(LKA)的仿真与建模。首先对比了车道偏离预警(LDW)和LKA的功能差异,强调LKA的主动干预特性。接着详细阐述了LKA系统架构,包括环境感知、决策控制等核心组件,并基于自行车模型建立车辆横向动力学方程。 文章重点演示了Simulink建模步骤:搭建车辆动力学模型、设计LKA控制器(采用LQR算法)、实现执行器接口和驾驶员干预检测。通过四个典型场景的仿真测试,验证了系统在直道行驶、弯道跟踪等工况下的控制性能,并给出了关键评价指标。最后展望了MPC控制、

amy_mhd的博客 224

Dart Isolate 全景解析

Isolate 的中文直译是“隔离区”。这个名字极其精准地道出了它的核心特征。•物理真相(操作系统视角):Isolate 确实是一个线程(Thread)。它由底层操作系统调度,能够真正利用多核 CPU 的并行计算能力。•逻辑真相(代码运行视角):它更像是一个微型进程(Mini Process)。因为它“六亲不认”,拥有极强的独立性。Main Isolate 并没有什么神权。它本质上和你在后台创建的 Isolate 一模一样,唯一的区别仅仅是它启动得最早,并绑定了 UI 渲染引擎而已。任务类型。

qq_21349039的博客 698

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

单线程的智慧:JavaScript异步编程的艺术 ——从“一根筋“到“运筹帷幄“

早期的JavaScript中,异步任务通过回调函数(Callback)串联,很快就陷入了臭名昭著的"回调地狱"——new Promise 时传入的函数会同步地、立刻地执行——它仅仅是一个"容器",用来容纳异步任务。readme中用了一个生动的比喻:进程是"董事长"(PID),线程是"经理"(Thread)。setTimeout的组合,我们巧妙地模拟了"等待2秒再做事"的效果——不是阻塞式的暂停,而是非阻塞式的延迟回调。单线程并没有变多线程,但它用"任务寄存 + 回头处理"的策略,实现了逻辑上的并发。

2501_93234401的博客 529

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

单线程的事件循环模型

所以呀,哪怕餐厅里有一万个客人,只要大管家转圈圈转得够快,厨师干活够利索,大家都会觉得:“哇,这家餐厅上菜真快!”,大管家马上记在小本本上,然后转头问厨师:“炒饭会做吗?等20分钟一到,厨师喊:“牛排好了!大管家就会把“等牛排”这件事记在“等待区的小本本”上,然后继续去接待其他客人、递纸条。那问题来了,如果外面有100个客人在排队,这个厨师会不会忙不过来,让客人等很久?- 厨师接单: 厨师说:“会做,但我现在正在切土豆丝,切完我就做!如果厨师说:“这个牛排要烤20分钟,你先去忙别的,烤好了我喊你。

blacklive233的博客 159

python异步方法async

Python async简单入门

love_521_的博客 955

消灭异步回调,还得是async-await

现在知道了,async-await是promise的语法糖了吧,不仅让我们书写代码时更加流畅,而且增强了代码的可读性。特别注意的是虽然async-await是建立在Promise机制之上的,但是并不能取代其地位,他们两者相辅相成,息息相关。其实async-await不止是Promise的语法糖,还是Generator的语法糖,Generator是什么?我们下篇见分晓。作者来碗盐焗星球链接https来源稀土掘金。...

猫老板的豆 415

企业级AI编排:MuleSoft如何让大语言模型融入核心业务系统

企业AI落地的核心瓶颈并非模型能力,而是智能如何与ERP、CRM、ServiceNow等关键业务系统安全、可靠、可审计地协同工作。AI编排(AI Orchestration)作为区别于简单自动化(Automation)的高阶范式,强调事务一致性、多源上下文融合、结构化输出解析与故障熔断等企业级能力。MuleSoft凭借其成熟的API治理、DataWeave数据编织、原生事务支持及混合云连接器生态,成为承载大语言模型进入生产环境的‘企业级操作系统’。本文聚焦采购风险预警等真实场景,详解如何通过七层Flow架构

weixin_34279579的博客 906

WuKongIM Web 管理台对接 Manager API 集成设计全解析

本文基于 WuKongIM 仓库中的设计文档 [2026-04-22-web-manager-api-integration-design.md](https://link.gitcode.com/i/911dd7b11e6530c45386e33988256c23),系统讲解如何把 `web/` 目录下已有的管理台页面骨架,对接上 `internal/access/manager` 已提供的真实

gitblog_00264的博客 1004
上一篇: Vue首屏性能分析和优化
下一篇: ruoyi(若依)框架使用说明(前后端分离)
普通网友
博客等级 码龄6年 3万+粉丝 481原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值