2016-10-14 83 views
1

你好,我是Promises的新手,並且在如何等待for循環中的所有promise後纔去下一個然後)。我見過幾個promise.all示例,但我不清楚如何使它們適用於我的以下代碼。它現在轉到for循環之後的next(),並在for循環完成之前解決。任何幫助表示讚賞!Promise for loops/promise.all,在節點中使用psql(pg-promise)

我正在使用pg-promise(帶有承諾的psql)。

原始代碼:

function getTeamMembers(aTeam) { 
    let promise = new Promise(function(resolve, reject) { 
     db.getTeamMembers(aTeam.tid) //return sql results rows 
     .then(function(rows){ 
      for(let i=0; i<rows.length; ++i) { //loop through each result row 
      getUserByUsername(rows[i].username) 
       .then(function(cfUser) { //add user from row to aTeam object      
       aTeam.addMember(cfUser); 
       }) 
       .catch(function(e) { 
       reject(e); 
       }); 
      } 
     }) 
     .then(function(){ 
      console.log(aTeam); //confirm added properly 
      resolve(aTeam); //resolve object 
     }) 
     .catch(function(e) { 
      console.log('addMemberToTeamByUsername: '+e.stack); 
      reject(e); 
     }); 
    }); 
    return promise; 
    } 

回答

2

我的pg-promise作者。

以下是有關在此環境中無效使用Promise.all現在刪除的答案的一些注意事項。


當使用表示物理資源的基於承諾的接口時,瞭解所使用的物理上下文非常重要。如果沒有它,你就有可能陷入瓶頸,因爲物理資源不像你的通用承諾解決方案那樣擴展。

pg-promise你的物理環境的情況下,由兩個東西組成:

  • 查詢字符串通過Node.js的IO可以通過管道連接池提供
  • 連接上下文

每個查詢請求都會從連接池中獲取並釋放連接,該連接池是非常有限的物理資源。您的默認池大小爲10,由底層驅動程序node-postgres設置。儘管你可以將它增加到100,但是這樣做會開始在連接管理上產生過載,所以它不是可擴展的。一個典型的增加值將被設置爲20,這大約是平均值。

因此,如果您在您的查詢數組上使用Promise.all,您的應用程序將幾乎立即耗盡該池,並且任何下一個到您的服務中的請求都將等待可用連接。

這樣的解決方案根本無法擴展,並且在此查詢時被列爲反模式:Tasks versus root/direct queries

基本上,它說明有您必須通過任務執行多個查詢:

  • 方法task,如果你不改變數據
  • 方法tx(交易),如果要更改數據

通過這種方式,您可以通過單個連接管理所有查詢,這對於實現服務的可伸縮性至關重要。


有大量的例子Learn By Example教程中兩個TasksTransactions


,並考慮到你正在試圖讓多發父行,然後多個子行,你應該看看這個問題:get JOIN table as array of results with PostgreSQL/NodeJS

我還建議閱讀Performance Boost文章,以更好地理解執行多個查詢的物理限制以及如何解決這些問題。

function getTeamMembers(aTeam) { 
    return db.task(t=> { 
     return t.map('SELECT * FROM team_members WHERE id=$1', aTeam.id, tm=> { 
      return t.any('SELECT * FROM users WHERE name=$1', tm.username) 
       .then(users=> { 
        tm.users = users; 
        return tm; 
       }); 
     }).then(t.batch); 
    }); 
} 

// usage example: 

getTeamMembers({id: 123}) 
    .then(members=> { 
     // members = array of member objects 
    }) 
    .catch(error=> { 
     // error 
    }); 

這是不這樣做的唯一途徑,但它是最短的;)

這種方法給出了以下問題更好的考慮:get JOIN table as array of results with PostgreSQL/NodeJS

+0

我不知道誰降低了這一點。但是,也許你應該添加一些代碼? – Bergi

+0

@Bergi,是的,我正忙着回答工作,當有機會的時候,會進一步細化。也被第一個答案作者(現已刪除)的批評無意中發現。我想這只是一個糟糕的一天。 –

+0

嗨維塔利 - 你能提供一些代碼作爲例子嗎?我很想看到它!我會看看你的建議,謝謝你幫助提升我的知識和代碼! –