NodeJS Streams-在管道中结束读取流,但仍处理已读取的块

tjvv9vkg  于 2023-05-17  发布在  Node.js
关注(0)|答案(1)|浏览(212)

我有以下问题:
我使用NodeJS流和管道来读取一个大文件,做一些转换,然后将其写入可写流。棘手的部分是,如果满足特定条件,我希望能够停止阅读文件,但仍然完成处理已经读取的块。
在下面的示例中,我正在阅读一个文本文件,我的转换流(secondStream)将文本转换为大写并发送到下一个流。但是如果它找到了一个文本,这意味着它应该停止从文本文件中阅读,我相信这意味着readstream应该停止读取块。
我尝试了几种解决方案,但不会线,我有点困惑在这里。到目前为止,我得到了以下代码。但是,通过使用firstStream.destroy();会使管道抛出错误
Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close
我能够通过在管道上捕获并忽略它来“避免”这个错误,但老实说,这对我来说听起来并不安全或正确。

const { Transform, Writable, Readable } = require("node:stream");
  const { pipeline } = require("node:stream/promises");
  const fs = require("node:fs");

  let shouldStop = false;
  const firstStream = fs.createReadStream("./lg.txt");

  const secondStream = new Transform({
    transform(chunk, encoding, callback) {
      const foundText = chunk.toString().search("CHAPTER 9") !== -1;

      if (foundText) {
        shouldStop = true;
      }

      const transformed = chunk.toString().toUpperCase();
      callback(null, transformed);
    },
  });

  const lastStream = process.stdout;

  firstStream.on("data", () => {
    if (shouldStop) {
      console.log("should pause");
      firstStream.destroy();
    }
  });

  await pipeline(firstStream, secondStream, lastStream).catch(
    (err) => undefined
  ); // Feels wrong to me

有更好的办法吗?我错过什么了吗?
提前感谢各位朋友!

bprjcwpo

bprjcwpo1#

在转换流中,您可以“吃掉”或“跳过”找到目标文本之后的任何数据。通过这种方式,您可以保留所有其他pipeline()逻辑。它不会立即终止,而是只读到输入流的末尾,但会跳过目标文本之后的所有数据。这允许流正常完成。

const secondStream = new Transform({
    transform(chunk, encoding, callback) {
        if (shouldStop) {
            // eat any remaining data
            callback(null, "");
        } else {
            const text = chunk.toString();
            const foundText = text.search("CHAPTER 9") !== -1;
            if (foundText) {
                // set flag to eat remaining data
                shouldStop = true;
            }
            callback(null, text.toUpperCase());
        }
    },
});

相关问题