浏览器的事件循环机制

Posted on Apr 10, 2024

浏览器的事件循环机制

核心概念

  • 事件循环(Event Loop)

    • 使得 JavaScript 异步编程成为可能的机制
    • 负责监听调用栈和消息队列,当调用栈为空时,将消息队列中的任务推入调用栈执行
  • 调用栈(Call Stack)

    • 用于追踪函数执行的栈结构
    • 当函数执行时,会被添加到栈顶;执行完毕后,会从栈顶移除
  • 消息队列(Message Queue)

    • 存储待处理消息的队列
    • 消息可以是用户产生的事件、定时器到期等

事件循环过程

  1. 执行全局脚本

    • 首先执行全局代码,将全局代码压入调用栈
  2. 事件循环启动

    • 全局代码执行完毕后,调用栈变为空,事件循环开始工作
  3. 从消息队列中取出任务

    • 事件循环从消息队列中取出一个任务
  4. 执行任务

    • 将取出的任务压入调用栈,执行任务
  5. 任务执行完毕

    • 任务执行完毕后,从调用栈中移除
  6. 重复步骤 3-5

    • 持续监听消息队列,重复上述过程

宏任务与微任务

  • 宏任务(Macro Task)

    • 如:setTimeoutsetInterval、I/O、UI 渲染等
    • 每次事件循环只从宏任务队列中取出一个任务执行
  • 微任务(Micro Task)

    • 如:Promise.thenMutationObserverqueueMicrotask
    • 当前宏任务执行完毕后,会执行所有队列中的微任务,再执行下一个宏任务

执行顺序

  1. 执行同步代码,这属于宏任务
  2. 执行栈为空,查询是否有微任务需要执行
  3. 执行所有微任务
  4. 必要的话渲染 UI
  5. 开始下一轮 Event Loop,执行宏任务中的异步代码,如 setTimeout 中的回调函数

特点

  • 非阻塞
    • 异步任务不会阻塞代码的执行,提高了代码的执行效率
  • 顺序控制
    • 通过事件循环机制,JavaScript 能够控制事件处理、定时器执行等的顺序