兼容旧版本的 Node.js


在 Node.js 0.10 之前,Readable 流接口更简单,但功能更弱,实用性也更低。

  • 'data' 事件将立即开始触发,而不是等待对 stream.read() 方法的调用。 需要执行一些工作来决定如何处理数据的应用程序需要将读取数据存储到缓冲区中,这样数据就不会丢失。
  • stream.pause() 方法是建议性的,而不是保证性的。 这意味着即使流处于暂停状态,仍然需要准备接收 'data' 事件。

在 Node.js 0.10 中,添加了 Readable 类。 为了与旧的 Node.js 程序向后兼容,当添加 'data' 事件处理程序或调用 stream.resume() 方法时,Readable 流会切换到“流动模式”。 效果是,即使不使用新的 stream.read() 方法和 'readable' 事件,也不再需要担心丢失 'data' 块。

虽然大多数应用程序将继续正常运行,但这会在以下情况下引入边缘情况:

  • 未添加 'data' 事件监听器。
  • 永远不会调用 stream.resume() 方法。
  • 流不会通过管道传输到任何可写目的地。

例如,考虑以下代码:

// 警告!破碎的!
net.createServer((socket) => {

  // 添加了 'end' 监听器,但从不使用数据。
  socket.on('end', () => {
    // 它永远不会到达这里。
    socket.end('The message was received but was not processed.\n');
  });

}).listen(1337);

在 Node.js 0.10 之前,传入的消息数据将被简单地丢弃。 但是,在 Node.js 0.10 及更高版本中,套接字永远处于暂停状态。

这种情况下的解决方法是调用 stream.resume() 方法开始数据流:

// 解决方法。
net.createServer((socket) => {
  socket.on('end', () => {
    socket.end('The message was received but was not processed.\n');
  });

  // 启动数据流,丢弃它。
  socket.resume();
}).listen(1337);

除了新的 Readable 流切换到流动模式之外,0.10 之前的样式流可以使用 readable.wrap() 方法封装在 Readable 类中。

Prior to Node.js 0.10, the Readable stream interface was simpler, but also less powerful and less useful.

  • Rather than waiting for calls to the stream.read() method, 'data' events would begin emitting immediately. Applications that would need to perform some amount of work to decide how to handle data were required to store read data into buffers so the data would not be lost.
  • The stream.pause() method was advisory, rather than guaranteed. This meant that it was still necessary to be prepared to receive 'data' events even when the stream was in a paused state.

In Node.js 0.10, the Readable class was added. For backward compatibility with older Node.js programs, Readable streams switch into "flowing mode" when a 'data' event handler is added, or when the stream.resume() method is called. The effect is that, even when not using the new stream.read() method and 'readable' event, it is no longer necessary to worry about losing 'data' chunks.

While most applications will continue to function normally, this introduces an edge case in the following conditions:

  • No 'data' event listener is added.
  • The stream.resume() method is never called.
  • The stream is not piped to any writable destination.

For example, consider the following code:

// WARNING!  BROKEN!
net.createServer((socket) => {

  // We add an 'end' listener, but never consume the data.
  socket.on('end', () => {
    // It will never get here.
    socket.end('The message was received but was not processed.\n');
  });

}).listen(1337);

Prior to Node.js 0.10, the incoming message data would be simply discarded. However, in Node.js 0.10 and beyond, the socket remains paused forever.

The workaround in this situation is to call the stream.resume() method to begin the flow of data:

// Workaround.
net.createServer((socket) => {
  socket.on('end', () => {
    socket.end('The message was received but was not processed.\n');
  });

  // Start the flow of data, discarding it.
  socket.resume();
}).listen(1337);

In addition to new Readable streams switching into flowing mode, pre-0.10 style streams can be wrapped in a Readable class using the readable.wrap() method.