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。
相关推荐
一斤代码32 分钟前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
3Katrina1 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
coderlin_2 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
伍哥的传说2 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
我在北京coding3 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
布兰妮甜3 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui
SevgiliD3 小时前
el-button传入icon用法可能会出现的问题
前端·javascript·vue.js
我在北京coding3 小时前
Element-Plus-全局自动引入图标组件,无需每次import
前端·javascript·vue.js
鱼 空3 小时前
解决el-table右下角被挡住部分
javascript·vue.js·elementui
小李飞飞砖4 小时前
React Native 组件间通信方式详解
javascript·react native·react.js