FORMA

其他常用模块

以下是 Node.js 中几个重要内置模块的详细介绍,涵盖事件触发器、定时器、加密、压缩、操作系统信息和实用工具。

一、事件触发器(events

events 模块是 Node.js 实现「事件驱动」架构的核心,许多内置模块(如 http.Serverstream)都继承自 EventEmitter

1. 自定义事件与继承 EventEmitter

js
const EventEmitter = require("events");

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on("event", (arg1, arg2) => {
    console.log("事件触发", arg1, arg2);
});
myEmitter.emit("event", "hello", "world");

也可以直接使用 EventEmitter 实例,不必要继承。

2. 内存管理:setMaxListeners

默认情况下,为同一个事件添加超过 10 个监听器会触发警告(防止内存泄漏)。可通过 setMaxListeners 调整限制:

js
myEmitter.setMaxListeners(20);
console.log(myEmitter.getMaxListeners()); // 20

若要彻底移除警告,可设为 0(不推荐)。

3. 其他常用方法

  • once(event, listener):只执行一次后自动移除。
  • prependListener:将监听器添加到数组头部。
  • removeListener / off:移除特定监听器。
  • removeAllListeners([event]):移除所有监听器。
  • listenerCount(event):获取监听器数量。
  • eventNames():返回已注册事件名称数组。

4. 错误处理

如果 EventEmitter 实例发生错误且没有监听 'error' 事件,Node.js 会抛出异常并打印堆栈。因此建议始终监听 'error' 事件。

js
myEmitter.on("error", err => {
    console.error("发生错误:", err);
});

二、定时器(timer

Node.js 的定时器与浏览器类似,但实现上基于 libuv 的事件循环,具有一些差异。

方法描述执行时机精度长时间延迟影响
setTimeout延迟执行一次在 timers 阶段(可能受其他回调阻塞)4ms 以内(嵌套调用)可能延迟
setInterval周期性执行每个周期尝试在 timers 阶段执行同上累积偏移
setImmediate尽快执行一次在 check 阶段(poll 阶段之后)较高几乎不受影响
process.nextTick尽快执行在当前阶段结束后、下个阶段开始前最高会阻塞事件循环

重要区别

  • setImmediatesetTimeout(fn, 0):在 I/O 循环中,setImmediate 总是先执行;在顶层模块中,顺序取决于性能(通常 setTimeout 可能随机先执行)。
  • process.nextTick 优先级最高,会递归导致 I/O 饥饿,官方推荐使用 setImmediate 或重构。

取消定时器clearTimeoutclearIntervalclearImmediate

js
const timeoutId = setTimeout(() => {}, 1000);
clearTimeout(timeoutId);

注意setInterval 可能因回调执行时间长而导致积压(下一次调用之前未完成),建议使用递归 setTimeout 实现精确间隔。

三、加密(crypto

crypto 模块提供加密功能,包含哈希、HMAC、对称/非对称加密及随机数生成。

1. 哈希(createHash

哈希算法(MD5、SHA-256 等)将任意长度数据转换为固定长度摘要,不可逆。

js
const crypto = require("crypto");

const hash = crypto.createHash("sha256");
hash.update("some data");
console.log(hash.digest("hex")); // 十六进制字符串

2. HMAC(基于哈希的消息认证码)

HMAC 需要密钥,用于验证消息完整性和真实性。

js
const hmac = crypto.createHmac("sha256", "secret-key");
hmac.update("message");
console.log(hmac.digest("hex"));

3. 对称加密

使用相同密钥加密和解密,如 AES。

js
const algorithm = "aes-256-cbc";
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);

const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update("plain text", "utf8", "hex");
encrypted += cipher.final("hex");

const decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(encrypted, "hex", "utf8");
decrypted += decipher.final("utf8");
console.log(decrypted); // 'plain text'

4. 非对称加密(RSA)

使用公钥加密,私钥解密。

js
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
    modulusLength: 2048,
});

const encrypted = crypto.publicEncrypt(publicKey, Buffer.from("secret"));
const decrypted = crypto.privateDecrypt(privateKey, encrypted);
console.log(decrypted.toString()); // 'secret'

5. 随机数生成

  • crypto.randomBytes(size):生成安全的伪随机字节。
  • crypto.randomInt(min, max):生成随机整数。
js
crypto.randomBytes(16, (err, buf) => {
    console.log(buf.toString("hex"));
});

四、压缩(zlib

zlib 模块提供 gzip、deflate、brotli 等压缩算法。

1. 压缩与解压(gzip 示例)

回调风格

js
const zlib = require("zlib");
const fs = require("fs");

const gzip = zlib.createGzip();
const inp = fs.createReadStream("input.txt");
const out = fs.createWriteStream("input.txt.gz");

inp.pipe(gzip).pipe(out);

Promise 风格(zlib.promises

js
const { promisify } = require("util");
const gzip = promisify(zlib.gzip);

async function compress(data) {
    const compressed = await gzip(data);
    console.log(compressed);
}

2. 常用方法

  • zlib.gzip(buf, callback) / gunzip
  • zlib.deflate / inflate
  • zlib.brotliCompress / brotliDecompress(Node.js 11.7+)

3. 内存与性能

压缩和解压是 CPU 密集型操作,建议在流中使用,避免一次性处理大文件。

五、操作系统信息(os

os 模块提供操作系统级别的系统信息。

方法描述
os.cpus()返回每个 CPU 核心的信息(型号、速度、时间)
os.totalmem() / os.freemem()总内存 / 空闲内存(字节)
os.networkInterfaces()网络接口信息(IPv4/IPv6、MAC 地址等)
os.loadavg()系统负载平均值(1, 5, 15 分钟)
os.EOL操作系统行结束符(\n\r\n
os.platform()操作系统平台('linux''win32''darwin'
os.homedir()当前用户的主目录
os.uptime()系统运行时间(秒)

示例:获取 CPU 核心数以优化子进程数量

js
const os = require("os");
const cpus = os.cpus().length;
console.log(`CPU 核心数: ${cpus}`);

六、实用工具(util

util 模块提供多种实用函数,帮助调试、类型转换和回调 Promise 化。

1. util.promisify

将遵循 Node.js 错误优先回调风格的函数转为返回 Promise 的函数。

js
const util = require("util");
const fs = require("fs");

const readFile = util.promisify(fs.readFile);
readFile("./file.txt", "utf8")
    .then(data => console.log(data))
    .catch(err => console.error(err));

2. util.types

提供一系列类型检查方法(比 typeofinstanceof 更可靠)。

js
const { types } = require("util");
console.log(types.isDate(new Date())); // true
console.log(types.isMap(new Map())); // true
console.log(types.isPromise(Promise.resolve())); // true

3. util.inspect

将对象格式化为字符串,用于调试。可通过 depthcolorsshowHidden 等选项控制。

js
const obj = { a: 1, b: { c: 2 } };
console.log(util.inspect(obj, { depth: 1, colors: true }));

Node.js 在内部使用 util.inspect 实现 console.log 的对象展示。

4. util.callbackify

async 函数(或返回 Promise 的函数)转换为错误优先的回调风格函数(与 promisify 相反)。

js
const { callbackify } = require("util");

async function asyncFn() {
    return "hello";
}
const callbackFn = callbackify(asyncFn);
callbackFn((err, ret) => {
    console.log(ret); // 'hello'
});

5. 其他

  • util.format(format, [...args]):类似 printf 的字符串格式化。
  • util.deprecate(fn, msg):标记方法已弃用,调用时会打印警告。

总结

模块核心用途常用场景
events实现事件驱动架构自定义事件、继承 EventEmitter
timer调度异步执行延迟、周期性、尽快执行
crypto加密与安全哈希、HMAC、对称/非对称加密、随机数
zlib数据压缩文件压缩、HTTP 传输压缩
os获取系统信息性能调优、资源监控
util通用工具回调转 Promise、类型检查、调试打印

这些模块构成了 Node.js 生态的重要基础,熟练掌握可以大幅提升开发效率和程序健壮性。

相关文章

Series

core

4 / 7