八股文-事件循环

50 阅读2分钟

JavaScript的事件循环机制是基于单线程执行的,这意味着JavaScript引擎在执行代码时,同一时间只能处理一个任务。为了处理I/O密集型或异步操作,JavaScript使用了事件循环(Event Loop)来管理任务队列和执行顺序。以下是JavaScript事件循环机制的基本组成部分:

任务被分为两大类:同步任务和异步任务。

  • 同步任务(Synchronous Tasks):这些任务是按照代码的顺序依次执行的,它们会阻塞主线程,直到任务完成。
  • 异步任务(Asynchronous Tasks):这些任务不会立即执行,而是会在将来的某个时间点执行。异步任务进一步分为宏任务(Macrotasks)和微任务(Microtasks)

常见的异步任务有如下几种

  1. Promise.then() ---微任务
  2. async/await ---Promise的语法糖 ---微任务
  3. setTimeout() ---宏任务
  4. setInterval() ---宏任务

事件循环流程

  1. 执行同步代码

    • JavaScript引擎开始执行主线程上的同步代码。
    • 在执行同步代码的过程中,如果遇到异步操作(如setTimeout、Promise等),这些异步操作的回调函数不会被立即执行,而是根据它们的类型被放入相应的队列。
  2. 分类异步操作

    • 宏任务(Macrotasks) :这些通常是较大的任务,如定时器回调(setTimeout、setInterval)、IO操作、UI渲染等。当遇到宏任务时,它们的回调函数会被放入宏任务队列(也称为任务队列)。
    • 微任务(Microtasks) :这些通常是较小的任务,如Promise的回调、MutationObserver等。当遇到微任务时,它们的回调函数会被放入微任务队列。
  3. 处理异步队列

    • 当主线程上的同步代码执行完毕后,JavaScript引擎会检查微任务队列。
    • 如果微任务队列中有任务,那么这些微任务会被依次执行,直到微任务队列为空。
    • 在所有微任务执行完毕后,事件循环可能会进行UI渲染更新。
    • 接着,事件循环会检查宏任务队列,并从宏任务队列中取出一个宏任务执行。
    • 执行完一个宏任务后,再次回到步骤3,首先检查并执行微任务队列中的任务。

这个过程会不断重复,形成事件循环。以下是一个简化的流程图:

执行同步代码
  |
  V
遇到异步操作 -> 放入宏任务队列或微任务队列
  |
  V
同步代码执行完毕
  |
  V
检查并执行微任务队列中的所有微任务
  |
  V
可能进行UI渲染更新
  |
  V
从宏任务队列中取出一个宏任务执行
  |
  V
回到步骤2,继续事件循环