产生多个承诺
我不确定这是可能的,但这是我想要做的。 我有一个数据库的调用返回一个承诺。 在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调用采取行动”,这可能意味着两件事之一。 你要么:
- 首先获取HTTP请求的所有结果,然后以某种方式处理每个结果,然后继续承诺链。
- 在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
,除了之前和之后。 在这两种情况下,整个链条都不会受到影响,因为您没有从then
callback中返回承诺。