流消费者的 API


几乎所有的 Node.js 应用程序,无论多么简单,都以某种方式使用流。 以下是在实现 HTTP 服务器的 Node.js 应用程序中使用流的示例:

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

const server = http.createServer((req, res) => {
  // `req` 是 http.IncomingMessage,它是可读流。
  // `res` 是 http.ServerResponse,它是可写流。

  let body = '';
  // 以 utf8 字符串形式获取数据。
  // 如果未设置编码,则将接收缓冲区对象。
  req.setEncoding('utf8');

  // 一旦添加了监听器,则可读流就会触发 'data' 事件。
  req.on('data', (chunk) => {
    body += chunk;
  });

  // 'end' 事件表示已经接收到整个正文。
  req.on('end', () => {
    try {
      const data = JSON.parse(body);
      // 给用户回写一些有趣的东西:
      res.write(typeof data);
      res.end();
    } catch (er) {
      // 哦哦!糟糕的 json!
      res.statusCode = 400;
      return res.end(`error: ${er.message}`);
    }
  });
});

server.listen(1337);

// $ curl localhost:1337 -d "{}"
// object
// $ curl localhost:1337 -d "\"foo\""
// string
// $ curl localhost:1337 -d "not json"
// error: Unexpected token o in JSON at position 1

Writable 流(例如示例中的 res)暴露了用于将数据写入流的方法,例如 write()end()

当数据可从流中读取时,Readable 流使用 EventEmitter API 来通知应用程序代码。 可以通过多种方式从流中读取可用数据。

WritableReadable 流都以各种方式使用 EventEmitter API 来传达流的当前状态。

DuplexTransform 流都是 WritableReadable

向流中写入数据或从流中消费数据的应用程序不需要直接实现流的接口,并且通常没有理由调用 require('node:stream')

希望实现新类型的流的开发者应参考流实现者的 API 章节。

Almost all Node.js applications, no matter how simple, use streams in some manner. The following is an example of using streams in a Node.js application that implements an HTTP server:

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

const server = http.createServer((req, res) => {
  // `req` is an http.IncomingMessage, which is a readable stream.
  // `res` is an http.ServerResponse, which is a writable stream.

  let body = '';
  // Get the data as utf8 strings.
  // If an encoding is not set, Buffer objects will be received.
  req.setEncoding('utf8');

  // Readable streams emit 'data' events once a listener is added.
  req.on('data', (chunk) => {
    body += chunk;
  });

  // The 'end' event indicates that the entire body has been received.
  req.on('end', () => {
    try {
      const data = JSON.parse(body);
      // Write back something interesting to the user:
      res.write(typeof data);
      res.end();
    } catch (er) {
      // uh oh! bad json!
      res.statusCode = 400;
      return res.end(`error: ${er.message}`);
    }
  });
});

server.listen(1337);

// $ curl localhost:1337 -d "{}"
// object
// $ curl localhost:1337 -d "\"foo\""
// string
// $ curl localhost:1337 -d "not json"
// error: Unexpected token o in JSON at position 1

Writable streams (such as res in the example) expose methods such as write() and end() that are used to write data onto the stream.

Readable streams use the EventEmitter API for notifying application code when data is available to be read off the stream. That available data can be read from the stream in multiple ways.

Both Writable and Readable streams use the EventEmitter API in various ways to communicate the current state of the stream.

Duplex and Transform streams are both Writable and Readable.

Applications that are either writing data to or consuming data from a stream are not required to implement the stream interfaces directly and will generally have no reason to call require('node:stream').

Developers wishing to implement new types of streams should refer to the section API for stream implementers.