Node.js 如何等待流完成管道?(Nodejs)

Node.js 如何等待流完成管道?(Nodejs),node.js,asynchronous,promise,pipe,pdftotext,Node.js,Asynchronous,Promise,Pipe,Pdftotext,我有一个承诺的for循环数组,所以我使用Promise.all遍历它们,然后调用它们 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.

我有一个承诺的for循环数组,所以我使用Promise.all遍历它们,然后调用它们

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;
        }
      });
    });    
  }
}
let promissions=[];
承诺。推动(承诺1);
承诺。推动(承诺2);
承诺。推动(承诺3);
承诺。所有(承诺)。然后((回应)=>{
for(设i=0;i<0.length;i++){
如果(promise.property==某物){
//做点什么
}否则{
让file=fs.createWriteStream('./hello.pdf');
让stream=responses[i]。管道(文件);
/*
我想要管道和下面的代码
在FOR循环的下一次迭代之前运行
*/
stream.on('finish',()=>{
//从pdf中提取文本
提取(文件路径,{splitPages:false},(错误,文本)=>{
如果(错误){
控制台日志(err);
}否则{
arrayOfDocuments[i].文本内容=文本;
}
});
});    
}
}

promise1、promise2和promise3是一些http请求,如果其中一个是应用程序/pdf,那么我将其写入一个流并解析其中的文本。但在解析pdf中的测试之前,此代码将运行下一次迭代。有没有办法让代码等到流的管道和提取完成后再移动到n到下一次迭代?

您可以将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) 
否则,您可以将流媒体部分作为原始/个人承诺的一部分来处理


到目前为止,您正在创建承诺并将其添加到数组中,而不是添加承诺。然后添加到数组中(这也是一个承诺)。然后在处理程序中执行流式处理。

以下类似操作也可以。我经常使用此模式:

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();
或将处理程序拆分为控制器和指定的处理程序:

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()

如果没有async/await,情况会非常糟糕。使用async/await,只需执行以下操作:

Promise.all(promises).then(async (responses) => {
  for (...) {
    await new Promise(fulfill => stream.on("finish", fulfill));
    //extract the text out of the PDF
  }
})

这不会在下一次迭代之前完成流。我仍然会在promise2完成对流的写入之前调用promise3。它不会等待,但当for循环中的下一次迭代发生时,它不会覆盖上一次的流,并且一切都并行工作。如果我想在for循环完成后使用该流,该怎么办我该如何使用这里的承诺来做到这一点?这就是beauti,封闭函数(
closure
),它保留
和任何其他内部变量,即使在
for循环
完成后也是如此。对于for循环的每次迭代,都会创建不同的流。这意味着在for循环完成后,对于您创建的每个流,都会触发finish事件。注意:仅限
finish
事件如果调用者正确处理流,则触发。如果没有(例如AWS SDK S3上载),则您可以使用
close
事件,以避免
Wait
永远坐在那里。您能帮助我理解
return new Promise()
Wait new Promise()之间的区别吗
?在您的代码示例中,我相信前者在每次迭代触发finish事件之前不会产生暂停程序执行的预期效果,而后者会。为什么会这样?(在我的特殊情况下,我使用的是
readable.pipe(writable)
在循环中,除非我将管道包装在
等待新承诺()
)中,否则查找迭代不会暂停。我不确定你在问什么。但是调用“等待”在循环内部,将暂停循环的执行,直到承诺解决为止,即直到
管道完成。因此,您将依次管道化流。不侦听流的错误事件不是一个好的做法。非常感谢…我有一些看似简单的代码由于流未刷新而无法工作ing.经过数小时的尝试,我发现这一点很有效。干杯!这是最好的回答,在我看来,在这种情况下,使用承诺是过分的,而且是限制性的(强制同步,这不在OP中)不侦听流的错误事件不是一种好的做法。事实上,这是一种未充分发挥生产代码作用的技术。具体而言,实现者需要决定是拒绝错误还是处理错误,然后让所有其他流完成。