产生多个承诺

我不确定这是可能的,但这是我想要做的。 我有一个数据库的调用返回一个承诺。 在then我想遍历的结果,并产生一个新的承诺每行进行HTTP请求。 它执行所有的HTTP请求,但是我不能为每个请求链接一个。 以下是我所尝试的:

尝试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所有的电话,但只跑了一次。 接下来我尝试了这个:

尝试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完全相同的行为。有没有办法做我想要的?

你很近 正如其他用户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() }); 

Promise.all是您的使用案例的理想select。 它会等待所有的makeFork承诺解决之前,继续链。 一旦承诺失败,它也会失败,并将错误正确地传播给你。

既然你在评论中说“你想对每个HTTP调用采取行动”,这可能意味着两件事之一。 你要么:

  1. 首先获取HTTP请求的所有结果,然后以某种方式处理每个结果,然后继续承诺链。
  2. 在parsing每个结果时处理,然后在处理完所有结果后继续执行诺言链。

第一个选项进一步分支,如果结果处理是:

  • asynchronous(返回一个承诺) :您将需要使用另一个Promise.all来处理来自makeFork所有结果。
  • 同步(不返回一个承诺) :你只是循环播放初始Promise.all得到的结果,并在那里进行处理。

以下是代码如何查找所有情况:

1. 首先解决所有请求,然后处理所有结果,然后继续下去

 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 }) 

您可以使用您在代码中的相同function作为processTeamResult的testing:

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

作为一个方面说明,你最后2次尝试做同样的事情,这是他们都冗余地附加另一个承诺makeFork ,除了之前和之后。 在这两种情况下,整个链条都不会受到影响,因为您没有从thencallback中返回承诺。