JS执行机制-event loop

event loop 是JS 执行机制,也是代码执行的开始。

要理解 Event Loop,我们需要了解以下几个关键概念:

  1. 调用栈 (Call Stack) : 这是 JavaScript 引擎执行代码的地方。当一个函数被调用时,它会被推入调用栈。当函数执行完毕后,它会从调用栈中弹出。JavaScript 代码的同步执行过程就是在这个栈中进行的。

  2. Web API (或 Node.js API) : 这些是浏览器(或 Node.js)提供的,用于处理异步任务的接口。例如:

    • setTimeout()setInterval() 用于定时器
    • fetch()XMLHttpRequest 用于网络请求
    • DOM 事件监听器(如 addEventListener

    当 JavaScript 代码调用这些 API 时,它们会将相应的任务交给浏览器或 Node.js 的底层线程去处理,而不会阻塞 JavaScript 主线程。

  3. 同步任务(Synchronous Tasks)和异步任务(Asynchronous Tasks)同步任务 是指那些在主线程上按顺序执行 的任务。 异步任务 是指那些耗时性的任务。它们不会阻塞主线程。

  4. 任务队列 (Task Queue / Callback Queue) : 当 Web API(或 Node.js API)处理完异步任务后,会将相应的回调函数放入一个队列中。这个队列通常被称为宏任务队列 (MacroTask Queue) 。常见的宏任务包括:

    • setTimeoutsetInterval
    • DOM 事件
    • I/O 操作
    • MessageChannel
    • setImmediate (Node.js 专属)
  5. 微任务队列 (MicroTask Queue) : 这是一个优先级更高的队列,用于存放微任务 (MicroTasks) 。微任务在宏任务执行完之后、下一个宏任务开始之前执行。常见的微任务包括:

    • Promisethen()catch()finally()
    • MutationObserver
    • queueMicrotask

Event Loop 的运行机制

Event Loop 的工作流程可以概括为以下步骤:

  1. 执行主线程同步代码:当 JavaScript 代码开始执行时,所有同步代码会被推入调用栈,并立即执行(JavaScript 代码执行相当于一个宏任务开始)。
  2. 清空调用栈:当调用栈中的所有同步代码执行完毕,调用栈变空。
  3. 检查微任务队列:Event Loop 会首先检查微任务队列。如果微任务队列中有任务,它会清空所有微任务,将它们依次推入调用栈执行,直到微任务队列为空。
  4. 检查宏任务队列 :在清空微任务队列后,Event Loop 会从宏任务队列中取出一个(注意:通常是一个)任务,将其对应的回调函数推入调用栈执行。
  5. 循环往复:当这个宏任务执行完毕,调用栈再次变空后,Event Loop 会回到步骤 3,再次检查微任务队列,然后是宏任务队列,如此循环往复,直到所有任务都被处理。

宏任务与微任务的优先级

理解宏任务和微任务的执行顺序是 Event Loop 的关键。总结来说:

  • 同步代码最先执行。
  • 微任务具有更高的优先级,它们会在当前宏任务执行完毕后立即执行,即使有新的宏任务已经准备好。
  • 每执行完一个宏任务,都会检查并清空微任务队列。

常见的宏任务和微任务

宏任务

  • script (整体代码):这是最开始执行的宏任务。
  • setTimeout() 和 setInterval():定时器回调函数。
  • setImmediate() (Node.js):在 I/O 事件之后,但在 setTimeout 和 setInterval 之前执行。
  • I/O (输入/输出):例如文件读写、网络请求等。
  • UI 渲染 (浏览器环境):页面的重绘和重排。
  • MessageChannel (浏览器和 Node.js):用于不同事件循环之间的通信。

微任务

  • Promise 的 then()、catch()、finally() 回调:Promise 状态改变后执行的回调。
  • process.nextTick() (Node.js):这是 Node.js 特有的,它比 Promise 回调的优先级更高,会在当前操作的末尾,下一个事件循环开始前执行。
  • MutationObserver (浏览器环境):用于监听 DOM 树变化的 API。
  • queueMicrotask():一个可以直接将函数添加到微任务队列的 API。
相关推荐
小高0071 小时前
协商缓存和强缓存
前端·javascript·面试
前端Hardy1 小时前
HTML&CSS&JS:超酷炫的一键登录页面
前端·javascript·css
该用户已不存在1 小时前
2025年,Javascript后端应该用 Bun、Node.js 还是 Deno?
javascript·后端
余_弦1 小时前
区块链钱包开发(十八)—— 构建批准控制器(ApprovalController)
javascript·区块链·以太坊
拭心1 小时前
一键生成 Android 适配不同分辨率尺寸的图片
android·开发语言·javascript
sorryhc1 小时前
CSR秒开有可能么?(附AI驱动学习实践推理过程)
前端·javascript·ai编程
龙井>_<1 小时前
vue项目封装axios请求,支持判断当前环境及判断token是否过期等等(详细教程,可复制粘贴代码)
前端·javascript·vue.js·前端框架
Juchecar2 小时前
跨端桌面框架 Tauri 架构原理 的通俗解读
javascript·node.js
Ice_Sugar_72 小时前
React 腾讯面试手写题
javascript·react.js·ecmascript
Jacob02342 小时前
Python与PostgreSQL实战:打造实时地理空间数据处理与管理系统
javascript·python·postgresql