node.js 如何等待流完成管道?(节点)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37837132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to wait for a stream to finish piping? (Nodejs)
提问by ThePumpkinMaster
I have a for loop array of promises, so I used Promise.all to go through them and called then afterwards.
我有一个 for 循环的 promise 数组,所以我使用 Promise.all 来遍历它们,然后调用 then 。
let promises = [];
promises.push(promise1);
promises.push(promise2);
promises.push(promise3);
Promise.all(promises).then((responses) => {
for (let i = 0; i < promises.length; i++) {
if (promise.property === something) {
//do something
} else {
let file = fs.createWriteStream('./hello.pdf');
let stream = responses[i].pipe(file);
/*
I WANT THE PIPING AND THE FOLLOWING CODE
TO RUN BEFORE NEXT ITERATION OF FOR LOOP
*/
stream.on('finish', () => {
//extract the text out of the pdf
extract(filePath, {splitPages: false}, (err, text) => {
if (err) {
console.log(err);
} else {
arrayOfDocuments[i].text_contents = text;
}
});
});
}
}
promise1, promise2, and promise3 are some http requests, and if one of them is an application/pdf, then I write it to a stream and parse the text out of it. But this code runs the next iteration before parsing the test out of the pdf. Is there a way to make the code wait until the piping to the stream and extracting are finished before moving on to the next iteration?
promise1、promise2 和 promise3 是一些 http 请求,如果其中一个是应用程序/pdf,那么我将其写入流并从中解析文本。但是这段代码在从 pdf 中解析测试之前运行下一次迭代。有没有办法让代码等到流的管道和提取完成后再进行下一次迭代?
回答by Hai Phan
Without async/await, it's quite nasty. With async/await, just do this:
没有 async/await,这很糟糕。使用异步/等待,只需执行以下操作:
Promise.all(promises).then(async (responses) => {
for (...) {
await new Promise(fulfill => stream.on("finish", fulfill));
//extract the text out of the PDF
}
})
回答by bknights
Something like the following would also work. I use this pattern fairly often:
像下面这样的东西也可以工作。我经常使用这种模式:
let promises = [];
promises.push(promise1);
promises.push(promise2);
promises.push(promise3);
function doNext(){
if(!promises.length) return;
promises.shift().then((resolved) =>{
if(resolved.property === something){
...
doNext();
}else{
let file = fs.createWriteStream('./hello.pdf');
let stream = resolved.pipe(file);
stream.on('finish', () =>{
...
doNext();
});
}
})
}
doNext();
or break up the handler to a controller and Promisified handler:
或将处理程序分解为控制器和 Promisified 处理程序:
function streamOrNot(obj){
return new Promise(resolve, reject){
if(obj.property === something){
resolve();
return;
}
let file = fs.createWriteStream...;
stream.on('finish', () =>{
...
resolve();
});
}
}
function doNext(){
if(!promises.length) return;
return promises.shift().then(streamOrNot).then(doNext);
}
doNext()
回答by Oxi
You can write the else part inside a self invoked function. So that the handling of stream will happen in parallel
您可以在自调用函数中编写 else 部分。这样流的处理将并行发生
(function(i) {
let file = fs.createWriteStream('./hello.pdf');
let stream = responses[i].pipe(file);
/*
I WANT THE PIPING AND THE FOLLOWING CODE
TO RUN BEFORE NEXT ITERATION OF FOR LOOP
*/
stream.on('finish', () => {
//extract the text out of the pdf
extract(filePath, {splitPages: false}, (err, text) => {
if (err) {
console.log(err);
}
else {
arrayOfDocuments[i].text_contents = text;
}
});
});
})(i)
Else you can handle the streaming part as part of the original/individual promise itself.
否则,您可以将流式传输部分作为原始/个人承诺本身的一部分进行处理。
As of now you are creating the promise and adding it to array, instead of that you add promise.then to the array(which is also a promise). And inside the handler to then you do your streaming stuff.
到目前为止,您正在创建承诺并将其添加到数组中,而不是将 promise.then 添加到数组(这也是一个承诺)。然后在处理程序中进行流式处理。

