管道传输到可写流时暂停可读流
Posted
技术标签:
【中文标题】管道传输到可写流时暂停可读流【英文标题】:Pause readable stream when piped to writable stream 【发布时间】:2021-03-03 08:35:54 【问题描述】:我有一个可读的流,我想暂停。它通过管道传输到可写流。我的代码是这样的
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 下载时,这不会暂停。
我认为这是因为我的可读流通过管道传输到可写流,而可写流要求更多数据,从而恢复流。如果我取消管道,这将解决问题。这是我取消管道时的代码
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
。这甚至可能吗?如果没有,我还有其他方法可以在通过管道传输到可读流时暂停流吗?
【问题讨论】:
【参考方案1】:我想通了。我不确定为什么这个解决方案有效,但它对我有用。我没有在暂停之前取消管道,而是为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;
);
);
【讨论】:
以上是关于管道传输到可写流时暂停可读流的主要内容,如果未能解决你的问题,请参考以下文章