Node环境的事件循环

news/2024/12/2 9:41:57/

文章目录

  • 前言
  • node简介
  • 六个阶段
    • (1)timer
    • (2)poll
    • (3) check阶段
  • Micro-Task Macro-Task
  • 注意点:
    • (1)setTImeOut setImmediate
    • (2)process.nextTick()

前言

参考文章:
浏览器与Node事件循环有何区别?

这么通俗易懂的Node事件循环,背就完了

node简介

Node 中的 Event Loop 和浏览器中的是完全不相同的东西。Node.js采用V8作为js的解析引擎,而I/O处理方面使用了自己设计的libuv,libuv是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的API,事件循环机制也是它里面的实现

六个阶段

在这里插入图片描述
从上图中,大致看出node中的事件循环的顺序:
外部输入数据–>轮询阶段(poll)–>检查阶段(check)–>关闭事件回调阶段(close callback)–>定时器检测阶段(timer)–>I/O事件回调阶段(I/O callbacks)–>闲置阶段(idle, prepare)–>轮询阶段(按照该顺序反复运行)…

  • timers 阶段:这个阶段执行timer(setTimeout、setInterval)的回调
  • I/O callbacks 阶段:处理一些上一轮循环中的少数未执行的 I/O 回调
  • idle, prepare 阶段:仅node内部使用
  • poll 阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里
  • check 阶段:执行 setImmediate() 的回调
  • close
    callbacks 阶段:执行 socket 的 close 事件回调
    上面六个阶段都不包括 process.nextTick()

接下去我们详细介绍timers、poll、check这3个阶段,因为日常开发中的绝大部分异步任务都是在这3个阶段处理的

(1)timer

timer阶段会执行setTimeout 和setInterval回调 并且是由poll阶段控制的,同样 在Node中定时器指定的时间也不是准确时间 只能是尽快执行

(2)poll

poll 是一个至关重要的阶段,这一阶段中,系统会做两件事情

1.回到 timer 阶段执行回调
2.执行 I/O 回调 并且在进入该阶段时如果没有设定了 timer 的话,会发生以下两件事情

如果 poll 队列不为空,会遍历回调队列并同步执行,直到队列为空或者达到系统限制 如果 poll 队列为空时,会有两件事发生

如果有 setImmediate 回调需要执行,poll 阶段会停止并且进入到 check 阶段执行回调 如果没有 setImmediate
回调需要执行,会等待回调被加入到队列中并立即执行回调,这里同样会有个超时时间设置防止一直等待下去

当然设定了 timer 的话且 poll 队列为空,则会判断是否有 timer 超时,如果有的话会回到 timer 阶段执行回调。

(3) check阶段

setImmediate()的回调会被加入check队列中,从event loop的阶段图可以知道,check阶段的执行顺序在poll阶段之后。

Micro-Task Macro-Task

Node端事件循环中的异步队列也是这两种:macro(宏任务)队列和 micro(微任务)队列。

常见的 macro-task 比如:setTimeout、setInterval、 setImmediate、script(整体代码)、 I/O 操作等。
常见的 micro-task 比如: process.nextTick、new Promise().then(回调)等。

注意点:

(1)setTImeOut setImmediate

二者非常相似 区别主要在于调用时机不同 他们的执行时机并不是固定的setTimeout 先 setImmediate后 因为事件循环有一定的准备阶段 当setTimeout没有准备好时 不会进入该次循环 该次只有setImmediate setTimeout会在下次循环中执行

(2)process.nextTick()

这个函数其实是独立于 Event Loop 之外的,它有一个自己的队列,当每个阶段完成后,如果存在 nextTick 队列,就会清空队列中的所有回调函数,并且优先于其他 microtask 执行。


http://www.ppmy.cn/news/1551716.html

相关文章

IDEA下载源码失败

问题说明 当在IDEA下载源码失败时,可是使用maven命令进行下载源码。 示例 打开终端进入项目目录,执行下面命令: mvn dependency:resolve -Dclassifiersources通过 -Dclassifiersources 参数,你可以指定 Maven 只下载源代码文件…

<<WTF-Solidity>>学习笔记(part 21-24)

part 21: 调用已部署合约 在Solidity中,一个合约可以调用另一个合约的函数,这在构建复杂的DApps时非常有用。本教程将会介绍如何在已知合约代码(或接口)和地址的情况下,调用已部署的合约。 part 22: Call call 是…

【人工智能基础05】决策树模型

文章目录 一. 基础内容1. 决策树基本原理1.1. 定义1.2. 表示成条件概率 2. 决策树的训练算法2.1. 划分选择的算法信息增益(ID3 算法)信息增益比(C4.5 算法)基尼指数(CART 算法)举例说明:计算各个…

Adversarial Learning forSemi-Supervised Semantic Segmentation

首先来了解一下对抗学习: 对抗样本:将真实的样本添加扰动而合成的新样本,是由深度神经网络的输入的数据和人工精心设计好的噪声合成得到的,但它不会被人类视觉系统识别错误。然而在对抗数据面前,深度神经网络却是脆弱…

在Window10或11系统中同时安装 JDK8 和 JDK11

在Window10或11系统中同时安装 JDK8 和 JDK11 最近写项目,之前的项目是用Java8环境开发的,在二次迭代中,但是新开发的项目采用Java11环境来开发,所以需要同时安装JDK8和JDK11环境,但是两个环境是不能同时使用的&#…

大模型开发和微调工具Llama-Factory-->LoRA合并

LoRA 合并 当我们基于预训练模型训练好 LoRA 适配器后,我们不希望在每次推理的时候分别加载预训练模型和 LoRA 适配器,因此我们需要将预训练模型和 LoRA 适配器合并导出成一个模型。根据是否量化以及量化算法的不同,导出的配置文件有所区别。…

大模型开发和微调工具Llama-Factory-->量化1(GPTQ 和 AWQ)

量化 大语言模型的参数通常以高精度浮点数存储,这导致模型推理需要大量计算资源。 量化技术通过将高精度数据类型存储的参数转换为低精度数据类型存储, 可以在不改变模型参数量和架构的前提下加速推理过程。这种方法使得模型的部署更加经济高效&#x…

第十六届蓝桥杯模拟赛(第一期)-Python

本次模拟赛我认为涉及到的知识点: 分解质因数 Python的datetime库 位运算 简单dp 1、填空题 【问题描述】 如果一个数 p 是个质数,同时又是整数 a 的约数,则 p 称为 a 的一个质因数。 请问 2024 有多少个质因数。 【答案提交】 这是一道结…