简体   繁体   English

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

[英]Pause readable stream when piped to writable stream

I have a readable stream that I would like to pause.我有一个我想暂停的可读流。 It is piped to a writable stream.它通过管道传输到可写流。 My code looks like this我的代码看起来像这样

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);
});

This works well on Mac.这在 Mac 上运行良好。 But for some reason, on Windows while downloading from an https URL, this doesn't pause.但出于某种原因,在 Windows 上从https URL 下载时,这不会暂停。

I think this is because my readable stream is piped to a writable stream and the writable stream is asking for more data, which resumes the stream.我认为这是因为我的可读流通过管道传输到可写流,而可写流要求更多数据,从而恢复流。 If I unpipe, this will solve the issue.如果我取消管道,这将解决问题。 Here is my code when I 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);
});

This actually causes my download to pause.这实际上导致我的下载暂停。 But this creates a new issue.但这会产生一个新问题。 After calling res.unpipe() , I still get data events.调用res.unpipe() ,我仍然收到数据事件。 This means that the few milliseconds in between calling res.unpipe() and res.pause() , some of my data is sent to the res pipe, but not written to writableStream pipe.这意味着在调用res.unpipe()res.pause()之间的几毫秒内,我的一些数据被发送到res管道,但没有写入writableStream管道。 This ends with my downloaded file getting corrupted.这以我下载的文件损坏而告终。

Is there any way to fix this problem?有没有办法解决这个问题? I'm not married to the idea of unpiping, it's just the only solution I could come up with.我并没有接受取消管道的想法,这只是我能想出的唯一解决方案。

I was thinking about storing the data the res gets when not piped to writableStream and manually passing it to writableStream when they pipe again.我正在考虑存储未通过管道传输到writableStreamres获得的数据,并在它们再次通过管道传输时手动将其传递给writableStream Is that even possible?这甚至可能吗? If not, are there other ways I can go about pausing a stream when piped to a readable stream?如果没有,是否有其他方法可以在通过管道传输到可读流时暂停流?

I figured it out.我想到了。 I'm not sure why this solution works, but it works for me.我不确定为什么这个解决方案有效,但它对我有用。 Instead of unpiping before I paused, I created a listener for pause and unpipe there.我没有在暂停之前取消管道,而是在那里创建了一个用于pause和取消管道的侦听器。 In addition, I also set res.readableFlowing to false manually.此外,我还手动将res.readableFlowing设置为 false。 With these two additions, I was able to pause and resume without the download file breaking.通过这两个添加,我能够在不破坏下载文件的情况下暂停和恢复。 Here's the implementation这是实现

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;
    }
  });
});

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

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