#7Event loop:宏任务与微任务

lencxlencx2022/07/25

事件循环

在计算机领域中事件循环(event loop),又称为消息分发器(message dispatcher)、消息循环(message loop)、消息泵(message pump)或运行循环(run loop),是一种程序构造或设计模式,负责等待并分发程序中的事件或消息。它的工作方式是向内部或者外部的“事件提供方”发出请求(请求通常会被阻塞,直到有新事件产生),待请求被处理后调用所获得的事件对应的回调函数(即“分发事件”)。

事件循环可以与反应器(reactor)结合使用,只要事件提供方采用可以被 poll(指类似 selectepoll 的系统调用,不是指轮询)的文件接口。事件循环几乎总是与消息发起方异步地执行。

当一个事件循环构成程序的中心控制流时(通常是这样),可以称之为主循环或者主事件循环。这些名称是合适的,因为这样的事件循环位于程序控制流的最顶层。

事件循环是实现进程间通信的方法之一。

JS 中的事件循环

事件循环的概念非常简单。有一个无限循环,JavaScript 引擎等待任务,执行它们然后休眠,等待更多任务。

Node.js

什么是事件循环 (What is the Event Loop)?

事件循环是 Node.js 处理非阻塞 I/O 操作的机制——尽管 JavaScript 是单线程处理的——当有可能的时候,它们会把操作转移到系统内核中去。
目前大多数内核都是多线程的,它们可在后台处理多种操作。当其中的一个操作完成的时候,内核通知 Node.js 将适合的回调函数添加到轮询队列中等待时机执行。

事件循环机制解析 (Event Loop Explained)

当 Node.js 启动后,它会初始化事件循环,处理已提供的输入脚本(或丢入到 REPL),它可能会调用一些异步的 API、调度定时器,或者调用 process.nextTick(),然后开始处理事件循环。

# 事件循环操作顺序的简化概览

# 1. 每个框为事件循环机制的一个阶段
# 2. 每个阶段都有一个 FIFO 队列来执行回调

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘
  • timers: 定时器 - 本阶段执行已经被 setTimeout()setInterval() 的调度回调函数。
  • pending callbacks: 待定回调 - 执行延迟到下一个循环迭代的 I/O 回调。
  • idle, prepare: 仅系统内部使用。
  • poll: 轮询 - 检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞。此阶段有两个重要功能:
    1. 计算应该阻塞和轮询 I/O 的时间。
    2. 然后,处理 轮询 队列里的事件。
  • check: 检测 - setImmediate() 回调函数在这里执行。
  • close callbacks: 关闭的回调函数 - 一些关闭的回调函数,如:socket.on('close', ...)

在每次运行的事件循环之间,Node.js 检查它是否在等待任何异步 I/O 或计时器,如果没有的话,则完全关闭。


参考资料

License Copyright © 2022-present lencx