2017-07-24 39 views
2

我不知道這是可能的,但這是我想要做的。我打電話給一個返回承諾的數據庫。在then我想遍歷結果併爲每行創建一個新的承諾來發出HTTP請求。它執行所有HTTP請求,但我無法爲每個請求鏈接一個then。這是我曾嘗試:產卵多重承諾

嘗試1

userDao.getBitbucketInfoForUser(token.id, cohortId) 
    // Get Bitbucket information and make clones 
    .then((teams) => { 
     for(const team of teams) { 
      console.log('Clone repo ' + sourceRepo + ' for Team-' + team.teamNumber); 
      return makeFork(gitInfo, sourceRepo, team); 
     } 
    }) 
    .then((result) => { 
     const team = result.team; 
     console.log('Wait for Team ' + team + ' repo'); 
    }) 
    .catch((error) => { 
     console.log(error); 
     response.status(error.status).json(error).end() 
    }); 

我馬上意識到,這是愚蠢的,因爲我回來,打破了我的循環。所以我去了這一點:

嘗試2

userDao.getBitbucketInfoForUser(token.id, cohortId) 
    // Get Bitbucket information and make clones 
    .then((teams) => { 
     for(const team of teams) { 
      console.log('Clone repo ' + sourceRepo + ' for Team-' + team.teamNumber); 
      makeFork(gitInfo, sourceRepo, team) 
       .then((result) => Promise.resolve(result)); 
     } 
    }) 
    .then((result) => { 
     const team = result.team; 
     console.log('Wait for Team ' + team + ' repo'); 
    }) 
    .catch((error) => { 
     console.log(error); 
     response.status(error.status).json(error).end() 
    }); 

這次經歷並取得所有的呼叫在makeFork但只跑了一次then。接下來,我想這:

嘗試3

userDao.getBitbucketInfoForUser(token.id, cohortId) 
    // Get Bitbucket information and make clones 
    .then((teams) => { 
     for(const team of teams) { 
      console.log('Clone repo ' + sourceRepo + ' for Team-' + team.teamNumber); 
      new Promise((resolve, reject) => resolve(makeFork(gitInfo, sourceRepo, team))); 
     } 
    }) 
    .then((result) => { 
     const team = result.team; 
     console.log('Wait for Team ' + result + ' repo'); 
    }) 
    .catch((error) => { 
     console.log(error); 
     response.status(error.status).json(error).end() 
    }); 

這導致了完全相同的行爲,嘗試2.有沒有辦法做我想要什麼?

+3

如何承諾所有? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all – Kosch

+0

我看到了,但它並不像我想要的東西。它需要一些有意義的東西,並且一旦它們全部解決,就會調用它。我可能需要這一點,但不是我想要對每個HTTP調用採取行動。 – CaseyB

回答

1

你很近。正如其他用戶Promise.all所指出的那樣,即使您需要單獨處理每個元素,也正是您想要的。

userDao.getBitbucketInfoForUser(token.id, cohortId) 
    // Get Bitbucket information and make clones 
    .then((teams) => { 
     // Act on each element individually. 
     const teamPromises = teams.map((team) => { 
      return makeFork(gitInfo, sourceRepo, team).then((result) => { 
       const team = result.team; 
       console.log('Wait for Team ' + team + ' repo'); 
      }); 
     }); 
     // Then resolve everything. 
     return Promise.all(teamPromises); 
    }) 
    .catch((error) => { 
     console.log(error); 
     response.status(error.status).json(error).end() 
    }); 
1

Promise.all非常適合您的使用情況。它會等待您的所有makeFork承諾在繼續連鎖之前解決。一旦承諾失敗,它也會失敗,並將錯誤正確地傳播到您的catch

既然你在評論中說「你想對每個HTTP調用採取行動」,這可能意味着兩件事之一。您要麼:

  1. 首先獲取HTTP請求的所有結果,然後以某種方式處理這些結果中的每一個,然後繼續承諾鏈。
  2. 處理解決的每個結果,然後在處理完所有結果後繼續處理承諾鏈。

第一個選項進一步分支取決於如果結果處理:

  • 異步(返回一個承諾):你需要使用另一個Promise.allmakeFork處理所有結果。
  • 同步(不返回承諾):您只需循環搜索初始Promise.all解決後獲得的結果,並在那裏進行處理。

下面的代碼如何能尋找所有情況:

首先解決所有請求,然後處理所有結果,然後繼續往下鏈

userDao.getBitbucketInfoForUser(token.id, cohortId) 
    .then(teams => Promise.all(
    teams.map(team => 
     makeFork(gitInfo, sourceRepo, team) 
    ) 
)) 

    // the next `then` will get called once all makeFork requests are successfully resolved 

    // use this if you have async processing of team results 
    .then(arrayOfResultsForEachMakeForkRequest => Promise.all(
    arrayOfResultsForEachMakeForkRequest.map(processTeamResult) 
)) 

    // or use this (without Promise.all) if you have sync processing of team results 
    .then(arrayOfResultsForEachMakeForkRequest => 
    arrayOfResultsForEachMakeForkRequest.map(processTeamResult) 
) 

    // either way, now you have your processed results 
    // this part of the chain will be reached after every result is obtained and processed 
    .then(processedResults => { 
    // ... 
    }) 
    .catch(reason => { 
    // this will get called if any of the promises in any part of the chain fails 
    }) 

2 。過程中的每個結果,因爲它進來,然後繼續向下,一旦所有的結果進行處理

userDao.getBitbucketInfoForUser(token.id, cohortId) 
    .then(teams => Promise.all(
    teams.map(team => 
     makeFork(gitInfo, sourceRepo, team) 
     .then(processTeamResult) // <-- the code will behave the same no matter if `processTeamResult` returns a promise that will resolve to a value or the value itself 
    ) 
)) 

    // this part of the chain will be reached after every result is obtained and processed 
    .then(processedResults => { 
    // ... 
    }) 
    .catch(reason => { 
    // this will get called if any of the promises in any part of the chain fails 
    }) 

你可以使用你在你的代碼作爲測試過的processTeamResult相同功能的鏈條:

const processTeamResult = (result) => { 
    console.log('Wait for Team ' + result.team + ' repo'); 
    return result; 
} 

作爲一個方面說明,你最後2次嘗試完全相同的事情,這是他們都冗餘地附加到另一個承諾makeFork,除了一個之前和之後。無論哪種情況,整個鏈條都不會受到影響,因爲您沒有回覆then回調中的承諾。