2017-09-05 107 views
0

假设我有使用承诺的NodeJS下面的源代码(连接3件藏品MongoDB的,好了,这并不重要)怎样才能保证解决与回调的多个层中的所有数据的NodeJS

function getData(){ 
    return new promise((resolve, reject) => { 
     var dataArray = []; 
     getCollection1().then((rows1) => { 
      getCollection2().then((rows2) => { 
       var val = someDataProcessingFunction(rows1, rows2); 
       dataArray.push(val); 

       resolve(dataArray); 
      }, (err) => { 
       reject(err); 
      } 
     }, (err) => { 
      reject(err); 
     }); 

     getCollection3().then((rows3) => { 
      rows3.forEach((row3) => { 
       dataArray.push(row3); 
      }); 
      resolve(dataArray); 
     }, (err) => { 
      reject(err); 
     }); 
    }); 
} 

的问题是,有多个地方dataArray推,但我不知道什么时候所有的推动完成。以便我不知道何时解决,将数据返回给用户,例如,通过response.send以express方式。至于上面的代码,当我使用多次解析时,我只会得到部分返回的数据。

我能想出两种解决方法,既不好。一个是围绕setTimeout中的所有解析,这意味着我必须延迟对用户的响应。

另一种方法是在开始时计算所有的推送时间,每次按一个项目时减1。当时间为0时,解决问题。但在进行实际循环之前往往难以计算数字。

有没有更好的解决方案?谢谢你,爱你:)

+0

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all –

+0

注意'then'回调只执行一次,所以我不明白为什么你有'dataArray',因为你只会推两次。 – trincot

+0

同样,你不能两次解决承诺。第二次调用'resolve'将不起作用。 – trincot

回答

1

首先,避免使用Promise constructor antipattern并改用返回值!对于多层异步功能,只需使用多层承诺。要一次等待多用,使用Promise.all

function getData(){ 
    return Promise.all([ 
     getCollection1(), 
     getCollection2(), 
     getCollection3() 
    ]).then(([rows1, rows2, rows3]) => { 
     return [someDataProcessingFunction(rows1, rows2)].concat(rows3); 
    }); 
} 
+0

非常感谢。我不知道Promise.all。但经过1天的学习,我仍然认为它不能解决我的问题,因为我有多个并行分支,有些分支有子分支,都可能产生部分结果数据。我不知道何时以及如何返回。然后功能。 Promise.all只解决了第一个并行层 – vdonkey

+0

之后,我发现了另一个解决方案:ES7 async/await。我可以使用async/await编写“真正的”同步功能。这样的生活更容易。我下载了NodeJS 8.4.0,在我的Ubuntu 16.04上使用新的async/await。它的工作和我的代码缩短了很多 – vdonkey

+0

你可以任意嵌套这些。为每个子结果做出承诺。在子结果数组上调用'Promise.all'。在'.then()'里面做这个子计算,再次返回一个promise。 [总是从每个函数返回](https://stackoverflow.com/a/25756564/1048572)。 – Bergi

相关问题