js中EventLoop


在 js 中,事件循环(Event Loop)是一个极其重要的概念,它确保了非阻塞的异步编程模型。理解事件循环不仅有助于我们编写更高效的代码,还能帮助我们更好地调试和优化应用程序。

什么是事件循环?

事件循环是 JavaScript 的一种控制结构,它允许你执行代码、收集事件并执行网络请求。在 JavaScript 的背景下,事件循环负责管理执行栈和消息队列之间的交互,从而实现非阻塞的异步操作。

js 的执行模型

javaScript 是一种单线程语言,这意味着它一次只能执行一个任务。为了实现异步操作,JavaScript 使用了执行栈(Call Stack)和消息队列(Message Queue)。

执行栈(Call Stack)

执行栈是一个后进先出的数据结构,当一个函数被调用时,它会被推入执行栈,执行完后会被弹出。(可以抽象的理解为打开抽屉,然后往抽屉里一本一本放书,拿出的时候,后放进去的书反而先拿出来)简单来说,执行栈管理着当前正在执行的代码。

消息队列(Message Queue)

消息队列则存放着待处理的事件和回调函数。当某个事件发生(例如点击按钮、网络请求完成等),相应的回调函数会被推入消息队列。当执行栈为空时,事件循环会从消息队列中取出函数并执行。

事件循环的工作机制

事件循环的基本流程如下:

  1. 执行栈为空:当执行栈为空时,事件循环会检查消息队列。
  2. 检查消息队列:如果消息队列中有待处理的事件,事件循环会将队列中的第一个事件取出,推入执行栈并执行。
  3. 重复以上步骤:执行完事件之后,事件循环又会检查消息队列,直到所有事件都被处理完。

示例说明

让我们通过一个简单的例子来更好地理解事件循环。

1
2
3
4
5
6
7
8
9
10
11
console.log("Start"); // 1

setTimeout(() => {
console.log("Timeout"); // 3
}, 0);

Promise.resolve().then(() => {
console.log("Promise"); // 2
});

console.log("End"); // 4

执行顺序分析

  1. console.log("Start") 被推入执行栈并立即执行,输出 Start
  2. setTimeout 被调用,将回调函数加入到宏任务队列(Message Queue),但不会立即执行。
  3. Promise.resolve().then(...) 被调用,将回调函数加入微任务队列(Microtask Queue)。
  4. console.log("End") 被推入执行栈并执行,输出 End
  5. 执行栈此时为空,事件循环会首先检查微任务队列,并发现有待执行的 Promise 回调,输出 Promise
  6. 执行完微任务之后,事件循环再检查宏任务队列,发现 setTimeout 的回调,输出 Timeout

输出顺序

因此,最终的输出顺序为:

1
2
3
4
Start
End
Promise
Timeout

微任务与宏任务

在 JavaScript 中,事件循环中有两个任务队列:微任务队列和宏任务队列。微任务队列的优先级高于宏任务队列。常见的微任务有 Promise 的回调,宏任务则包括 setTimeoutsetInterval

ok这样我们就理解了事件循环机制了。

我的微信公众号: 梨的前端小屋


文章作者: 梨啊梨
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 梨啊梨 !
  目录