Node.js 中 Stream 模块全部 API 详解
一、Stream 基础概念
javascript
const { Stream } = require('stream');
// 1. Stream 类型
// - Readable: 可读流
// - Writable: 可写流
// - Duplex: 双工流
// - Transform: 转换流
// 2. Stream 事件
// - data: 数据可读时触发
// - end: 数据读取完成时触发
// - error: 发生错误时触发
// - finish: 数据写入完成时触发
// - close: 流关闭时触发
// - pipe: 流被管道连接时触发
// - unpipe: 流取消管道连接时触发
二、Readable 流
javascript
const { Readable } = require('stream');
// 1. 创建可读流
class MyReadable extends Readable {
constructor(options) {
super(options);
this.data = ['a', 'b', 'c'];
}
_read() {
const chunk = this.data.shift();
if (chunk) {
this.push(chunk);
} else {
this.push(null); // 结束流
}
}
}
// 2. 使用可读流
const readable = new MyReadable();
readable.on('data', (chunk) => {
console.log('收到数据:', chunk);
});
readable.on('end', () => {
console.log('数据读取完成');
});
// 3. 暂停和恢复
readable.pause(); // 暂停读取
readable.resume(); // 恢复读取
// 4. 销毁流
readable.destroy(); // 销毁流
// 5. 设置编码
readable.setEncoding('utf8'); // 设置编码
// 6. 取消管道连接
readable.unpipe(); // 取消所有管道连接
readable.unpipe(writable); // 取消特定管道连接
// 7. 检查流状态
console.log('是否可读:', readable.readable);
console.log('是否暂停:', readable.isPaused());
三、Writable 流
javascript
const { Writable } = require('stream');
// 1. 创建可写流
class MyWritable extends Writable {
constructor(options) {
super(options);
}
_write(chunk, encoding, callback) {
console.log('写入数据:', chunk);
callback(); // 写入完成
}
_final(callback) {
console.log('写入完成');
callback();
}
}
// 2. 使用可写流
const writable = new MyWritable();
writable.write('Hello'); // 写入数据
writable.end('World'); // 写入数据并结束流
// 3. 设置编码
writable.setDefaultEncoding('utf8'); // 设置默认编码
// 4. 检查流状态
console.log('是否可写:', writable.writable);
console.log('是否已结束:', writable.writableEnded);
console.log('是否已完成:', writable.writableFinished);
// 5. 销毁流
writable.destroy(); // 销毁流
// 6. 清空缓冲区
writable.cork(); // 暂停写入
writable.uncork(); // 恢复写入
四、Duplex 流
javascript
const { Duplex } = require('stream');
// 1. 创建双工流
class MyDuplex extends Duplex {
constructor(options) {
super(options);
this.data = ['a', 'b', 'c'];
}
_read() {
const chunk = this.data.shift();
if (chunk) {
this.push(chunk);
} else {
this.push(null);
}
}
_write(chunk, encoding, callback) {
console.log('写入数据:', chunk);
callback();
}
}
// 2. 使用双工流
const duplex = new MyDuplex();
duplex.on('data', (chunk) => {
console.log('收到数据:', chunk);
});
duplex.write('Hello');
duplex.end();
五、Transform 流
javascript
const { Transform } = require('stream');
// 1. 创建转换流
class MyTransform extends Transform {
constructor(options) {
super(options);
}
_transform(chunk, encoding, callback) {
// 转换数据
const transformed = chunk.toString().toUpperCase();
this.push(transformed);
callback();
}
_flush(callback) {
// 流结束时的处理
this.push('END');
callback();
}
}
// 2. 使用转换流
const transform = new MyTransform();
transform.on('data', (chunk) => {
console.log('转换后数据:', chunk);
});
transform.write('hello');
transform.end();
六、管道操作
javascript
const { Readable, Writable } = require('stream');
// 1. 基本管道操作
readable.pipe(writable);
// 2. 链式管道
readable
.pipe(transform1)
.pipe(transform2)
.pipe(writable);
// 3. 管道事件
readable.on('pipe', (source) => {
console.log('开始管道连接');
});
writable.on('unpipe', (source) => {
console.log('取消管道连接');
});
// 4. 错误处理
readable.on('error', (err) => {
console.error('读取错误:', err);
});
writable.on('error', (err) => {
console.error('写入错误:', err);
});
七、实用工具函数
javascript
const { pipeline, finished } = require('stream');
// 1. pipeline 函数
pipeline(
readable,
transform,
writable,
(err) => {
if (err) {
console.error('管道错误:', err);
} else {
console.log('管道完成');
}
}
);
// 2. finished 函数
finished(readable, (err) => {
if (err) {
console.error('流结束错误:', err);
} else {
console.log('流正常结束');
}
});
八、实际应用示例
javascript
const { Readable, Writable, Transform } = require('stream');
const fs = require('fs');
const zlib = require('zlib');
// 1. 文件流操作
// 读取文件
const readStream = fs.createReadStream('input.txt');
// 写入文件
const writeStream = fs.createWriteStream('output.txt');
// 管道连接
readStream.pipe(writeStream);
// 2. 压缩文件
const gzip = zlib.createGzip();
fs.createReadStream('input.txt')
.pipe(gzip)
.pipe(fs.createWriteStream('output.txt.gz'));
// 3. 解压文件
const gunzip = zlib.createGunzip();
fs.createReadStream('input.txt.gz')
.pipe(gunzip)
.pipe(fs.createWriteStream('output.txt'));
// 4. 自定义转换流
class UppercaseTransform extends Transform {
_transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
}
}
// 5. 流式数据处理
const processData = new UppercaseTransform();
fs.createReadStream('input.txt')
.pipe(processData)
.pipe(fs.createWriteStream('output.txt'));
// 6. 错误处理
processData.on('error', (err) => {
console.error('处理错误:', err);
});
// 7. 流控制
let paused = false;
processData.on('data', (chunk) => {
if (paused) {
processData.pause();
}
});
// 8. 内存管理
const CHUNK_SIZE = 1024 * 1024; // 1MB
fs.createReadStream('large-file.txt', { highWaterMark: CHUNK_SIZE })
.pipe(fs.createWriteStream('output.txt'));
九、高级特性
javascript
const { Readable, Writable, Transform } = require('stream');
// 1. 背压处理
class BackpressureWritable extends Writable {
constructor(options) {
super(options);
this.highWaterMark = options.highWaterMark || 16384;
}
_write(chunk, encoding, callback) {
// 检查缓冲区大小
if (this.writableLength >= this.highWaterMark) {
// 暂停读取
this.emit('drain');
callback(new Error('背压'));
} else {
// 继续写入
callback();
}
}
}
// 2. 自定义缓冲区
class CustomBuffer extends Transform {
constructor(options) {
super(options);
this.buffer = Buffer.alloc(0);
}
_transform(chunk, encoding, callback) {
// 添加到缓冲区
this.buffer = Buffer.concat([this.buffer, chunk]);
// 处理完整的数据块
while (this.buffer.length >= 1024) {
const data = this.buffer.slice(0, 1024);
this.buffer = this.buffer.slice(1024);
this.push(data);
}
callback();
}
_flush(callback) {
// 处理剩余数据
if (this.buffer.length > 0) {
this.push(this.buffer);
}
callback();
}
}
// 3. 流组合
class StreamComposer extends Transform {
constructor(streams) {
super();
this.streams = streams;
}
_transform(chunk, encoding, callback) {
// 处理多个流
let result = chunk;
for (const stream of this.streams) {
result = stream._transform(result, encoding);
}
this.push(result);
callback();
}
}
// 4. 流监控
class StreamMonitor extends Transform {
constructor(options) {
super(options);
this.stats = {
bytesProcessed: 0,
chunksProcessed: 0,
startTime: Date.now()
};
}
_transform(chunk, encoding, callback) {
// 更新统计信息
this.stats.bytesProcessed += chunk.length;
this.stats.chunksProcessed++;
// 输出统计信息
console.log('处理统计:', this.stats);
this.push(chunk);
callback();
}
}
十、最佳实践
javascript
const { Readable, Writable, Transform } = require('stream');
// 1. 错误处理
function handleStreamError(stream, error) {
console.error('流错误:', error);
stream.destroy();
}
// 2. 资源清理
function cleanupStream(stream) {
stream.removeAllListeners();
stream.destroy();
}
// 3. 性能优化
function optimizeStream(stream, options) {
stream.setMaxListeners(options.maxListeners || 10);
stream.setEncoding(options.encoding || 'utf8');
}
// 4. 流控制
function controlStream(stream, options) {
const { highWaterMark, lowWaterMark } = options;
stream.on('drain', () => {
console.log('缓冲区已清空');
});
stream.on('error', (err) => {
console.error('流错误:', err);
});
}
// 5. 流组合
function composeStreams(streams) {
return streams.reduce((prev, curr) => {
return prev.pipe(curr);
});
}
// 6. 流监控
function monitorStream(stream) {
const stats = {
startTime: Date.now(),
bytesProcessed: 0,
chunksProcessed: 0
};
stream.on('data', (chunk) => {
stats.bytesProcessed += chunk.length;
stats.chunksProcessed++;
});
stream.on('end', () => {
const duration = Date.now() - stats.startTime;
console.log('流统计:', {
...stats,
duration,
throughput: stats.bytesProcessed / duration
});
});
return stats;
}
Stream 模块的主要特点:
- 提供流式数据处理能力
- 支持多种流类型
- 提供丰富的操作方法
- 高效的内存管理
- 支持背压处理
使用建议:
- 正确处理错误
- 注意内存使用
- 合理使用背压
- 及时清理资源
- 监控流性能