Node.js 流的事件

Node.js 的 Stream(流)是处理流式数据的抽象接口。Readable 与 Writable 流都继承自 EventEmitter,因此都通过事件进行交互。

可写流(Writable)

  • close:底层资源(如文件描述符)被关闭后触发。
  • drain:写队列清空、内核缓冲区可继续写入时触发;用于处理背压。
  • error:写入或管道过程中出错时触发。
  • finish:调用 end() 后所有数据被写入时触发。
  • pipe:可读流的 pipe() 把目标流加入管道时触发。
  • unpipe:可读流 unpipe() 移除目标流时触发。

可读流(Readable)

  • close:底层资源关闭后触发。
  • data:每读到一块数据时触发(以流模式 / flowing mode 工作时)。
  • end:所有数据被消费完后触发。
  • error:读取过程中出错时触发。
  • pause:调用 pause() 或流进入暂停模式时触发。
  • readable:有数据可读、可以调用 read() 时触发(以非流模式 / paused mode 工作时)。

来源整理自:vue3js.cn 面试官系列

补充

补充:两段最常用的事件循环示例,强调 drain 与 pipe 在处理大文件时的关键作用。

const fs = require('node:fs');

// 写大文件,注意背压:write 返回 false 时等待 drain 再继续
const ws = fs.createWriteStream('big.txt');
function writeMillionLines(i = 0) {
  while (i < 1_000_000) {
    const ok = ws.write(`line ${i}\n`);
    if (!ok) { ws.once('drain', () => writeMillionLines(i + 1)); return; }
    i++;
  }
  ws.end();
}
writeMillionLines();
ws.on('finish', () => console.log('done'));

// 读大文件:data + end 是最直观的写法
const rs = fs.createReadStream('big.txt');
rs.on('data', (chunk) => process.stdout.write(chunk));
rs.on('end', () => console.log('\nend'));
rs.on('error', (err) => console.error(err));