繁体   English   中英

stream 管道上的 Node.Js 异步迭代器

[英]Node.Js async iterator over stream pipeline

我有以下管道:

readFile > parseCSV > otherProcess

readFile是标准的 Node.Js createReadStream ,而 parseCSV 是 Node.js 转换 stream (模块链接)。

我想逐行遍历 csv 文件并同时处理一行。 因此,流和异步迭代器是绝配。

我有以下正常工作的代码:

async function* readByLine(path, opt) {
  const readFileStream = fs.createReadStream(path);
  const csvParser = parse(opt);
  const parser = readFileStream.pipe(csvParser);
  for await (const record of parser) {
    yield record;
  }
}

我对 Node.Js 流很陌生,但我从许多来源中了解到,模块stream.pipeline优于.pipe读取流的方法。

如何更改上面的代码以使用stream.pipeline (实际上是从util.promisify(pipeline)获得的 promise 版本)并当时产生一行?

您实际上应该能够将 fs-stream 和 parser-stream 都传递给pipeline()并在 parser-stream 上使用您的异步迭代器:

const fs = require('fs');
const parse = require('csv-parse');
const stream = require('stream')
const util = require('util');
const pipeline = util.promisify(stream.pipeline);

async function* readByLine(path, opt) {
    const readFileStream = fs.createReadStream(path);
    const csvParser = parse(opt);
    await pipeline(readFileStream, csvParser);
    for await (const record of csvParser) {
        yield record;
    }
}

添加到@eol 的答案中,我建议存储 promise 并在异步迭代后await它。

const fs = require('fs');
const parse = require('csv-parse');
const stream = require('stream');

async function* readByLine(path, opt) {
    const readFileStream = fs.createReadStream(path);
    const csvParser = parse(opt);
    const promise = stream.promises.pipeline(readFileStream, csvParser);
    for await (const record of csvParser) {
        yield record;
    }
    await promise;
}

通过在循环之前调用await pipeline(...) ,它将消耗整个 stream ,然后您可以从缓冲区中剩余的任何内容进行迭代,这在小流上是偶然的,但可能会在更大(或无限/懒惰)上中断) 流。

回调等价物可能会根据我们await的位置更清楚正在发生的事情。

// await before iterating
stream.pipeline(a, b, err => {
  if (err) return callback(err)

  for await (const record of b) {
    // process record
  }

  callback()
}

// await after iterating
for await (const record of stream.pipeline(a, b, callback)) {
  // process record
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM