当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Node.js stream.pipeline(streams, callback)用法及代码示例


stream.pipeline(streams, callback)

历史
版本变化
v18.0.0

将无效回调传递给 callback 参数现在会抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK

v14.0.0

pipeline(..., cb) 将在调用回调之前等待 'close' 事件。该实现尝试检测遗留流,并且仅将此行为应用于预计会发出 'close' 的流。

v13.10.0

添加对异步生成器的支持。

v10.0.0

添加于:v10.0.0


参数

在流和生成器之间传递错误并正确清理并在管道完成时提供回调的模块方法。

const { pipeline } = require('node:stream');
const fs = require('node:fs');
const zlib = require('node:zlib');

// Use the pipeline API to easily pipe a series of streams
// together and get notified when the pipeline is fully done.

// A pipeline to gzip a potentially huge tar file efficiently:

pipeline(
  fs.createReadStream('archive.tar'),
  zlib.createGzip(),
  fs.createWriteStream('archive.tar.gz'),
  (err) => {
    if (err) {
      console.error('Pipeline failed.', err);
    } else {
      console.log('Pipeline succeeded.');
    }
  }
);

pipeline API 提供了一个 Promise 版本,它还可以接收选项参数作为带有 signal <AbortSignal> 属性的最后一个参数。当信号中止时,将在底层管道上调用 destroy ,并带有 AbortError

const { pipeline } = require('node:stream/promises');

async function run() {
  await pipeline(
    fs.createReadStream('archive.tar'),
    zlib.createGzip(),
    fs.createWriteStream('archive.tar.gz')
  );
  console.log('Pipeline succeeded.');
}

run().catch(console.error);

要使用 AbortSignal ,请将其作为最后一个参数传递到选项对象中:

const { pipeline } = require('node:stream/promises');

async function run() {
  const ac = new AbortController();
  const signal = ac.signal;

  setTimeout(() => ac.abort(), 1);
  await pipeline(
    fs.createReadStream('archive.tar'),
    zlib.createGzip(),
    fs.createWriteStream('archive.tar.gz'),
    { signal },
  );
}

run().catch(console.error); // AbortError

pipeline API 还支持异步生成器:

const { pipeline } = require('node:stream/promises');
const fs = require('node:fs');

async function run() {
  await pipeline(
    fs.createReadStream('lowercase.txt'),
    async function* (source, { signal }) {
      source.setEncoding('utf8');  // Work with strings rather than `Buffer`s.
      for await (const chunk of source) {
        yield await processChunk(chunk, { signal });
      }
    },
    fs.createWriteStream('uppercase.txt')
  );
  console.log('Pipeline succeeded.');
}

run().catch(console.error);

请记住处理传递给异步生成器的 signal 参数。特别是在异步生成器是管道的源(即第一个参数)或管道永远不会完成的情况下。

const { pipeline } = require('node:stream/promises');
const fs = require('node:fs');

async function run() {
  await pipeline(
    async function* ({ signal }) {
      await someLongRunningfn({ signal });
      yield 'asd';
    },
    fs.createWriteStream('uppercase.txt')
  );
  console.log('Pipeline succeeded.');
}

run().catch(console.error);

stream.pipeline() 将在所有流上调用 stream.destroy(err),除了:

  • Readable 已发出 'end''close' 的流。
  • Writable 已发出 'finish''close' 的流。

在调用 callback 后,stream.pipeline() 将悬空事件侦听器留在流上。在失败后重用流的情况下,这可能会导致事件侦听器泄漏和吞噬错误。如果最后一个流是可读的,悬空的事件侦听器将被移除,以便稍后可以使用最后一个流。

stream.pipeline() 在引发错误时关闭所有流。 IncomingRequestpipeline 一起使用可能会导致意外行为,一旦它会破坏套接字而不发送预期的响应。请参见下面的示例:

const fs = require('node:fs');
const http = require('node:http');
const { pipeline } = require('node:stream');

const server = http.createServer((req, res) => {
  const fileStream = fs.createReadStream('./fileNotExist.txt');
  pipeline(fileStream, res, (err) => {
    if (err) {
      console.log(err); // No such file
      // this message can't be sent once `pipeline` already destroyed the socket
      return res.end('error!!!');
    }
  });
});

相关用法


注:本文由纯净天空筛选整理自nodejs.org大神的英文原创作品 stream.pipeline(streams, callback)。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。