2016-08-29 31 views
1

我想我儘可能地防止嵌套查詢,但我實在不確定。我明白這裏的調用都可以在單個select查詢中執行,但我這樣做是爲了簡化示例。如何防止在集合中嵌套查詢/捕獲?

// This example is in TypeScript 

// find user 
User.find({where:{username:'user'}}) 

    // if found user 
    .then(function(user) { 

     return User.find({where:{username:'other_user'}}) 

      // if found other_user 
      .then(function(other_user) { 
       // do stuff 
       return whatever_i_need 
      } 

      // if something went wrong, go straight to parent catch 
      .catch(function(err) { 
       // do stuff 
       throw new Error() 
      } 
    } 

    // if previous .then() returned success 
    .then(function(data) { 

     return User.find({where:{username:'yet_another_user'}}) 

      // if found yet_another_user 
      .then(function(yet_another_user) { 
       // do stuff 
       return whatever_i_need_again 
      } 

      // if something went wrong, go straight to parent catch 
      .catch(function(err) { 
       // do stuff 
       throw new Error() 
      } 
    } 

    // if anything threw an error at any point in time 
    .catch(function(err) { 
     // handle the error 
    } 

但是,這導致了嵌套的承諾,這正是承諾的意圖是防止。這是承諾推薦的「最大深度」,還是我錯過了某些東西?有沒有更好的方式來鏈接查詢?

+0

'這導致嵌套的承諾,而這正是承諾是爲了prevent.' - 有些情況下,嵌套承諾是必要的。不要說這是一個例子,但不要盲目地相信你讀到的有關Promises的所有內容:p –

回答

2

返回嵌套承諾,而不是在內部塊中處理它以平坦化結構。

User.find({where:{username:'user'}}) 
.then(function(user) { 
    if (user) { // if found user 
    // do stuff 
    return User.find({where:{username:'other_user'}}); 
    } 
    throw new Error('user not-found'); 
}) 
.then(function(other_user) { 
    if (other_user) { // if found other_user 
    // do stuff 
    return whatever_i_need; 
    } 
    throw new Error('other_user not-found'); 
}) 
.then(function(data) { 
    return User.find({where:{username:'yet_another_user'}}) 
}) 
.then(function(yet_another_user) { 
    if (yet_another_user) { // if found yet_another_user 
    // do stuff 
    return whatever_i_need_again; 
    } 
    throw new Error('yet_another_user not-found'); 
} 
.then(function(data){ 
    // do stuff 
}) 
.catch(function(err) { // if anything threw an error at any point in time 
    // handle the error 
} 

請注意,已解決的承諾意味着查詢已成功完成。這就是全部。成功的查詢不保證結果被返回。空結果是已解決承諾的有效結果。

還要注意,來自解析或拒絕回調函數的返回值將使用已解析的承諾進行包裝,然後傳遞給下一個then塊,從而形成一個有意義的承諾鏈。感謝@ Matt關於這一點的後續反饋。

+0

因此,這個流程對每個查詢使用'.then()',而對另一個'.then()'使用'.then()'來分析結果? – Matt

+0

@Matt,是的,這就是流量如何變平。 – Season

+0

@Matt,我假設你想拋出錯誤,以提早退出鏈,如果沒有找到感興趣的用戶。如果情況並非如此,則以其他方式以其他方式處理。 – Season

1

兩點:

  • .catch(function(err) { throw new Error() }。它什麼也不做,只是刪除錯誤信息。
  • 可以unnestthen電話

所以它只是應該

User.find({where:{username:'user'}}) 
.then(function(user) { 
    return User.find({where:{username:'other_user'}}) 
}) 
.then(function(other_user) { 
    // do stuff 
    return whatever_i_need 
}) 
// if previous .then() returned success 
.then(function(data) { 
    return User.find({where:{username:'yet_another_user'}}) 
}) 
// if found yet_another_user 
.then(function(yet_another_user) { 
    // do stuff 
    return whatever_i_need_again 
}) 
// if anything threw an error at any point in time 
.catch(function(err) { 
    // handle the error 
}) 
+0

這與上述答案類似,對不對?爲每個查詢使用2'.then()'調用。第一個'.then()'用於後續查詢,第二個'.then()'用於處理結果? 此外,很好的覆蓋錯誤。我混合了一些代碼,那些應該是'if(row is valid){return data} else {throw new Error()}'。 – Matt

+0

@Matt啊,我知道,他們是相似的。如果你不做2個異步事件,你不需要2個''then'',你通常可以將一個promise-returning調用合併到前面的同步調用中。順便說一句,如果這個邏輯在任何地方都一樣,你可能想把它抽象成一個額外的函數。 – Bergi