Node-回眸[二]

Node-回眸[二]

💡 原文中文,约50100字,阅读约需120分钟。
📝

内容提要

本文系统讲解Node.js核心模块,包括事件机制(发布订阅模式、EventEmitter、error事件)、util工具(类型判断、promisify、inspect、format)、fs文件系统(读写、流、文件描述符、inode、链接)、Stream四种流与pipe管道、crypto加密(摘要、HMAC、对称与非对称加密、数字签名)、zlib压缩,以及脚手架、markdown渲染等实战应用。

🔎

延伸解读

发布订阅模式:解耦事件驱动架构

文章通过手写 SubPub 类展示了发布订阅模式的四个核心方法:on、once、off、emit。发布者与订阅者通过调度中心完全解耦,消息按主题广播。这种模式在 Node 的 EventEmitter 和前端 Vue2 的 eventBus 中均有体现。理解其实现有助于排查事件监听器泄漏或消息未触发的问题,例如未先订阅就发布会导致消息丢失。

EventEmitter 的 error 事件与监听器上限

Node 内置的 EventEmitter 是许多核心类(如 Process、Stream、HTTP)的基类。文章强调:若未为 error 事件注册监听器,触发时会直接抛出错误并导致进程退出,因此最佳实践是始终监听 error。此外,默认单个事件最多 10 个监听器,超出会发出内存泄漏警告,可通过 setMaxListeners 调整。这提醒开发者注意监听器数量,避免潜在泄漏。

fs 模块的同步、回调与 Promise 三种风格

文章指出 fs 的所有文件操作方法都提供同步、异步回调和基于 Promise 三种形式。同步方法会阻塞事件循环,异步回调和 Promise 版本则使用 libuv 线程池在后台执行。对于大文件,应使用 createReadStream 和 createWriteStream 分块处理,避免一次性读入内存。同时,操作完成后必须关闭文件描述符,否则可能导致内存泄漏。

Stream 管道与链式处理的实际应用

文章通过示例展示了 pipe 如何将可读流、转换流和可写流连接起来,实现边读边写。例如读取大文件、转换为大写、压缩并写入文件,整个过程无需将文件全部加载到内存。pipe 内部封装了 data 和 end 事件,自动管理背压,防止快速可读流淹没可写流。这种模式适合处理大文本、图片响应或日志压缩等场景。

❓

Q&A

Node.js 的发布订阅模式是怎么工作的?

发布订阅模式有三个角色:发布者、订阅者和调度中心。发布者发布消息并指定主题,订阅者通过主题订阅消息,调度中心维护消息列表并提供 on、once、off、emit 等方法,将发布者和订阅者解耦。

EventEmitter 的 error 事件没监听会怎样?

如果 EventEmitter 实例触发了 error 事件但没有注册监听器,Node.js 会抛出错误并打印堆栈跟踪,然后进程退出。最佳实践是始终为 error 事件添加监听器。

util.promisify 和手写 promisify 有什么区别?

util.promisify 能将回调函数转为 Promise,并且原回调函数的参数(除 err 外)会作为对象的属性返回。手写 promisify 无法获取原参数名,因此不能像 util.promisify 那样 resolve 一个对象,底层通过 kCustomPromisifyArgsSymbol 获取 key 名,但该 API 仅 Node 内部使用。

fs.createReadStream 适合读取大文件吗?为什么?

适合。createReadStream 创建可读流,不会一次性将文件读取到内存,而是分块读取,减轻内存压力,适合大文件。

Node.js 中 Stream 有哪几种类型?

Stream 有四种类型:Readable(可读流)、Writable(可写流)、Duplex(可读可写流,读写独立)、Transform(可读可写流,读写过程中可修改数据)。

crypto 模块中对称加密和非对称加密有什么区别?

对称加密使用相同的密钥进行加密和解密,常见算法有 AES、DES 等;非对称加密使用一对公钥和私钥,公钥加密、私钥解密,解决了密钥分发问题。

🏷️

标签

➡️

继续阅读