JavaScript 事件循环(Event Loop)

JavaScript 事件循环(Event Loop)

JavaScript 事件循环(Event Loop)

什么是事件循环?

事件循环是JavaScript实现异步编程的核心机制。JavaScript是单线程语言,通过事件循环来处理异步操作,避免阻塞主线程。

详解:

JavaScript 在设计之初便是单线程,即指程序运行时,只有一个线程存在,同一时间只能做一件事。
为什么要这么设计,跟JavaScript的应用场景有关
JavaScript 初期作为一门浏览器脚本语言,通常用于操作 DOM ,如果是多线程,一个线程进行了删除 DOM ,另一个添加 DOM,此时浏览器该如何处理?
为了解决单线程运行阻塞问题,JavaScript用到了计算机系统的一种运行机制,这种机制就叫做事件循环(Event Loop)

图解:

在这里插入图片描述

核心概念

1. 调用栈(Call Stack)

  • 存储函数执行上下文
  • 遵循后进先出(LIFO)原则
  • 同步代码在这里执行

2. 任务队列(Task Queue)

分为两种:

宏任务(Macro Task)

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

微任务(Micro Task)

  • Promise.then/catch/finally
  • async/await
  • MutationObserver
  • process.nextTick(Node.js,优先级最高)

3. 执行顺序

  1. 执行同步代码(调用栈)
  2. 执行所有微任务
  3. 执行一个宏任务
  4. 执行所有微任务
  5. 重复步骤3-4

初等难度练习题

console.log(1)setTimeout(()=>{ console.log(2)},0)newPromise((resolve, reject)=>{ console.log('new Promise')resolve()}).then(()=>{ console.log('then')}) console.log(3)

解题顺序

// 遇到 console.log(1) ,直接打印 1// 遇到定时器,属于新的宏任务,留着后面执行// 遇到 new Promise,这个是直接执行的,打印 'new Promise'// .then 属于微任务,放入微任务队列,后面再执行// 遇到 console.log(3) 直接打印 3// 好了本轮宏任务执行完毕,现在去微任务列表查看是否有微任务,发现 .then 的回调,执行它,打印 'then'// 当一次宏任务执行完,再去执行新的宏任务,这里就剩一个定时器的宏任务了,执行它,打印 2

中等难度练习题

console.log('1');setTimeout(()=>{ console.log('2'); Promise.resolve().then(()=>{ console.log('3');});},0); Promise.resolve().then(()=>{ console.log('4');setTimeout(()=>{ console.log('5');},0);});newPromise((resolve)=>{ console.log('6');resolve();}).then(()=>{ console.log('7');});setTimeout(()=>{ console.log('8'); Promise.resolve().then(()=>{ console.log('9');});},0); console.log('10');

题目要求

请写出上述代码的输出顺序,并解释原因。


答案解析

输出顺序:1 → 6 → 10 → 4 → 7 → 2 → 3 → 8 → 9 → 5

console.log('1');// 第一轮,同步代码。输出“1”setTimeout(()=>{// 第一轮,宏任务1加入队列 console.log('2');// 第三轮,执行宏任务1。输出“2” Promise.resolve().then(()=>{// 第三轮,立即执行微任务3。 console.log('3');// 第三轮,输出“3”});},0); Promise.resolve().then(()=>{// 第一轮, 微任务1加入队列 console.log('4');// 第二轮,执行微任务1。输出“4”setTimeout(()=>{// 第二轮,产生新的宏任务3 console.log('5');// 第五轮,执行宏任务3,输出“5”},0);});newPromise((resolve)=>{//第一轮, 同步。构造函数同步执行 console.log('6');//第一轮,输出“6”。resolve();}).then(()=>{// 第一轮,微任务2加入队列 console.log('7');// 第二轮,执行微任务2,输出“7”});setTimeout(()=>{// 第一轮,宏任务2加入队列。 console.log('8');// 第四轮,执行宏任务2。输出“8” Promise.resolve().then(()=>{// 第四轮,产生微任务4。 console.log('9');// 第四轮,立即执行微任务4,输出“9”});},0); console.log('10');//第一轮, 同步代码。输出“10”

详细执行过程

第一轮(同步代码):

  1. console.log('1') → 输出 1
  2. setTimeout(...) → 宏任务1加入队列
  3. Promise.resolve().then(...) → 微任务1加入队列
  4. new Promise(...) 构造函数同步执行 → 输出 6
  5. .then(...) → 微任务2加入队列
  6. setTimeout(...) → 宏任务2加入队列
  7. console.log('10') → 输出 10

第二轮(清空微任务):

  1. 执行微任务1:输出 4,同时产生新的宏任务3
  2. 执行微任务2:输出 7

第三轮(执行宏任务1):

  1. 输出 2,产生微任务3
  2. 立即执行微任务3:输出 3

第四轮(执行宏任务2):

  1. 输出 8,产生微任务4
  2. 立即执行微任务4:输出 9

第五轮(执行宏任务3):

  1. 输出 5

关键点总结

  1. Promise构造函数是同步的,只有.then是异步的
  2. 微任务优先级高于宏任务,每次宏任务后都会清空所有微任务
  3. setTimeout即使延迟为0,也会被放入宏任务队列
  4. 在宏任务中产生的微任务会在该宏任务执行完后立即执行

实际应用场景

1. 优化性能

// 使用微任务批量更新DOMlet updates =[];functionscheduleUpdate(data){ updates.push(data); Promise.resolve().then(()=>{// 批量处理所有更新processBatch(updates); updates =[];});}

2. 确保执行顺序

asyncfunctionfetchData(){const data =awaitfetch('/api/data');// 这里的代码会在微任务中执行 console.log('数据获取完成');}

3. 避免阻塞

functionheavyTask(){setTimeout(()=>{// 将耗时操作放入宏任务// 避免阻塞UI渲染performHeavyComputation();},0);}

常见面试问题

  1. 微任务和宏任务的区别?
    • 微任务在当前事件循环结束前执行,宏任务在下一个事件循环执行
    • 微任务优先级更高
  2. async/await 的执行顺序?
    • await 后面的代码相当于放在 Promise.then
  3. Node.js 中的 process.nextTick?
    • 优先级高于所有微任务,在当前操作完成后立即执行

参考资源

Read more

保姆级教程:Windows下安装OpenClaw + 接入飞书机器人,看这一篇就够了!

文章目录 * 前言 * ⚠️ 重要提示:隐私安全优先 * 第一部分:Windows环境准备 * 1.1 系统要求 * 1.2 安装nvm for Windows(推荐) * 1.3 安装Node.js 22.x版本 * 第二部分:安装OpenClaw * 2.1 一键安装脚本(推荐) * 2.2 初始化配置 * 2.3 启动服务并验证 * 第三部分:配置大模型API(核心前提) * 第四部分:飞书机器人配置(核心步骤) * 4.1 安装飞书插件 * 4.2 创建飞书企业自建应用 * 4.3 添加机器人能力 * 4.4

By Ne0inhk
【讨论】VR + 具身智能 + 人形机器人:通往现实世界的智能接口

【讨论】VR + 具身智能 + 人形机器人:通往现实世界的智能接口

摘要:本文探讨了“VR + 具身智能 + 人形机器人”作为通往现实世界的智能接口的前沿趋势。文章从技术融合、应用场景、商业潜力三个维度分析其价值,涵盖工业协作、教育培训、医疗康复、服务陪护等领域,并展望VR赋能下的人机共生未来,揭示具身智能如何推动机器人真正理解、感知并参与现实世界。 VR + 具身智能 + 人形机器人:通往现实世界的智能接口 文章目录 * VR + 具身智能 + 人形机器人:通往现实世界的智能接口 * 一、引言:三股力量的融合,正在重塑现实世界 * 二、具身智能:让AI拥有“身体”的智慧 * 1. 什么是具身智能(Embodied Intelligence) * 2. 为什么VR是具身智能的“孵化器” * 三、VR + 具身智能 + 人形机器人:协同结构与原理 * 1. 系统组成 * 2. 人类的“

By Ne0inhk

Modelsim仿真软件的,安装/破解/使用教程大全

仿真前言         作为一名FPGA工程师,在做FPGA开发时,使用仿真一定是最重要的,有些人喜欢写完代码直接上板子调试,根本不会做一点点仿真;如果是简单的逻辑代码,有十足的把握,那就不用仿真,可以直接上板子调试,但是,如果您是在做工程的开发,很多代码都是第一次编写调试,那么,代码的仿真是一定要做的,你要问我为啥,我个人觉得,每次把自己写完的代码,放到modelsim上面仿真看一下波形,就像考试的时候,拿着参考答案在做题一样的感觉,各个波形的变化你都会看的一清二楚,但是如果你用在线逻辑分析仪看RTL的仿真,那真的是太耗费时间;         我知道这个时候就会有人说了,Modelsima仿真有啥用呀,和下板子调试完全是两个概念,包括信号延迟,信号质量,眼图等都不一样,说的也对,但是实际情况是,这些人眼高手低,觉得仿真这种操作太麻烦;仿真虽然不能完全模拟真实的硬件信号,硬件延迟也没法准确仿真,但是他能让你在开发的时候,规避掉95%的因为代码引起的错误,这会让你在调试阶段节省很多时间;然后剩下的调试你必须 要在硬件调试时才会发现并且解决;        在调试阶段,FPGA为

By Ne0inhk