2017-09-05 102 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

相關問題