管道传输到可写流时暂停可读流

Pause readable stream when piped to writable stream

我有一个可读的流,我想暂停。它通过管道传输到可写流。我的代码看起来像这样

const { get } = require('https');
const { createWriteStream };

const writableStream = createWriteStream(SOME_PATH);
get(SOME_URL, (res) => {
  res.pipe(writableStream);
  setTimeout(() => {
    res.pause();
  }, 2000);

  setTimeout(() => {
    res.resume();
  }, 4000);
});

这在 Mac 上运行良好。但出于某种原因,在 Windows 从 https URL 下载时,这不会暂停。

我认为这是因为我的可读流通过管道传输到可写流,而可写流正在请求更多数据,从而恢复流。如果我取消管道,这将解决问题。这是我 unpipe

时的代码
const writableStream = createWriteStream(SOME_PATH);
get(SOME_URL, (res) => {
  res.pipe(writableStream);
  setTimeout(() => {
    res.unpipe(writableStream);
    res.pause();
  }, 2000);

  setTimeout(() => {
    res.pipe(writableStream);
    res.resume();
  }, 4000);
});

这实际上导致我的下载暂停。但这会产生一个新问题。调用 res.unpipe() 后,我仍然收到数据事件。这意味着在调用 res.unpipe()res.pause() 之间的几毫秒内,我的一些数据被发送到 res 管道,但没有写入 writableStream 管道。这以我下载的文件损坏而告终。

有什么办法可以解决这个问题吗?我不接受拆管道的想法,这只是我能想到的唯一解决方案。

我正在考虑存储 res 在未通过管道传输到 writableStream 时获取的数据,并在它们再次通过管道传输时手动将其传递给 writableStream。这可能吗?如果没有,是否有其他方法可以在通过管道传输到可读流时暂停流?

我明白了。我不确定为什么这个解决方案有效,但它对我有用。我没有在暂停之前取消管道,而是为 pause 创建了一个侦听器并在那里取消管道。此外,我还手动将 res.readableFlowing 设置为 false。通过这两项添加,我能够在不破坏下载文件的情况下暂停和恢复。这是实现

let isPaused = false;
const writableStream = createWriteStream(SOME_PATH);
get(SOME_URL, (res) => {
  res.pipe(writableStream);
  setTimeout(() => {
    isPaused = true;
    res.pause();
  }, 2000);

  setTimeout(() => {
    isPaused = false;
    res.pipe(writableStream);
    res.resume();
  }, 4000);

  res.on('pause', () => {
    // Add this flag because pause event gets called many times, and we only
    // want this code to happen when we call it manually
    if (isPaused) {
      res.unPipe(writableStream);
      res.readableFlowing = false;
    }
  });
});