readable.unshift(chunk[, encoding])


  • chunk <Buffer> | <Uint8Array> | <string> | <null> | <any> 要取消转移到读取队列的数据块。 对于不在对象模式下运行的流,chunk 必须是字符串、BufferUint8Arraynull。 对于对象模式的流,chunk 可以是任何 JavaScript 值。
  • encoding <string> 字符串块的编码。 必须是有效的 Buffer 编码,例如 'utf8''ascii'

chunk 作为 null 传入信号流结束 (EOF),其行为与 readable.push(null) 相同,之后无法写入更多数据。 EOF 信号放在缓冲区的末尾,任何缓冲的数据仍将被刷新。

readable.unshift() 方法将数据块推回内部缓冲区。 这在某些情况下很有用,其中流被代码消费,需要"取消消耗"它已经从源中提取的一定数量的数据,以便数据可以传给其他方。

'end' 事件触发后不能调用 stream.unshift(chunk) 方法,否则会抛出运行时错误。

使用 stream.unshift() 的开发者通常应该考虑改用 Transform 流。 有关更多信息,请参阅流实现者的 API 章节。

// 拉出由 \n\n 分隔的标题。
// 如果获取太多,则使用 unshift()。
// 使用 (error, header, stream) 调用回调。
const { StringDecoder } = require('node:string_decoder');
function parseHeader(stream, callback) {
  stream.on('error', callback);
  stream.on('readable', onReadable);
  const decoder = new StringDecoder('utf8');
  let header = '';
  function onReadable() {
    let chunk;
    while (null !== (chunk = stream.read())) {
      const str = decoder.write(chunk);
      if (str.includes('\n\n')) {
        // 找到标题边界。
        const split = str.split(/\n\n/);
        header += split.shift();
        const remaining = split.join('\n\n');
        const buf = Buffer.from(remaining, 'utf8');
        stream.removeListener('error', callback);
        // 在取消移位之前删除 'readable' 监听器。
        stream.removeListener('readable', onReadable);
        if (buf.length)
          stream.unshift(buf);
        // 现在可以从流中读取消息的正文。
        callback(null, header, stream);
        return;
      }
      // 仍在阅读标题。
      header += str;
    }
  }
}

stream.push(chunk) 不同,stream.unshift(chunk) 不会通过重置流的内部读取状态来结束读取过程。 如果在读取期间调用 readable.unshift()(即从自定义流上的 stream._read() 实现中调用),这可能会导致意外结果。 在立即调用 stream.push('') 之后调用 readable.unshift() 将适当地重置读取状态,但是最好避免在执行读取过程中调用 readable.unshift()

  • chunk <Buffer> | <Uint8Array> | <string> | <null> | <any> Chunk of data to unshift onto the read queue. For streams not operating in object mode, chunk must be a string, Buffer, Uint8Array, or null. For object mode streams, chunk may be any JavaScript value.
  • encoding <string> Encoding of string chunks. Must be a valid Buffer encoding, such as 'utf8' or 'ascii'.

Passing chunk as null signals the end of the stream (EOF) and behaves the same as readable.push(null), after which no more data can be written. The EOF signal is put at the end of the buffer and any buffered data will still be flushed.

The readable.unshift() method pushes a chunk of data back into the internal buffer. This is useful in certain situations where a stream is being consumed by code that needs to "un-consume" some amount of data that it has optimistically pulled out of the source, so that the data can be passed on to some other party.

The stream.unshift(chunk) method cannot be called after the 'end' event has been emitted or a runtime error will be thrown.

Developers using stream.unshift() often should consider switching to use of a Transform stream instead. See the API for stream implementers section for more information.

// Pull off a header delimited by \n\n.
// Use unshift() if we get too much.
// Call the callback with (error, header, stream).
const { StringDecoder } = require('node:string_decoder');
function parseHeader(stream, callback) {
  stream.on('error', callback);
  stream.on('readable', onReadable);
  const decoder = new StringDecoder('utf8');
  let header = '';
  function onReadable() {
    let chunk;
    while (null !== (chunk = stream.read())) {
      const str = decoder.write(chunk);
      if (str.includes('\n\n')) {
        // Found the header boundary.
        const split = str.split(/\n\n/);
        header += split.shift();
        const remaining = split.join('\n\n');
        const buf = Buffer.from(remaining, 'utf8');
        stream.removeListener('error', callback);
        // Remove the 'readable' listener before unshifting.
        stream.removeListener('readable', onReadable);
        if (buf.length)
          stream.unshift(buf);
        // Now the body of the message can be read from the stream.
        callback(null, header, stream);
        return;
      }
      // Still reading the header.
      header += str;
    }
  }
}

Unlike stream.push(chunk), stream.unshift(chunk) will not end the reading process by resetting the internal reading state of the stream. This can cause unexpected results if readable.unshift() is called during a read (i.e. from within a stream._read() implementation on a custom stream). Following the call to readable.unshift() with an immediate stream.push('') will reset the reading state appropriately, however it is best to simply avoid calling readable.unshift() while in the process of performing a read.