當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


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)。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。