我不确定这是可能的,但这正是我想要做的。我调用了一个返回promise的数据库。在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
中的所有通话,但只运行了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完全相同的行为。有没有办法做我想做的事?
答案 0 :(得分:1)
Promise.all
非常适合您的使用案例。在继续链之前,它将等待您的所有makeFork
承诺解决。一旦其中一个承诺失败并将错误正确地传播到catch
,它也会失败。
由于您在评论中说您“想要对每个HTTP呼叫采取行动”,这可能意味着两件事之一。你想要:
第一个选项进一步分支,具体取决于结果处理是:
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
})
您可以使用代码中的相同功能作为processTeamResult
的测试:
const processTeamResult = (result) => {
console.log('Wait for Team ' + result.team + ' repo');
return result;
}
作为旁注,你最近的两次尝试都是完全相同的,这是因为他们都冗余地将另一个承诺附加到makeFork
,除了之前和之后的承诺。在任何一种情况下,整个链都不会受到影响,因为您没有从then
回调中返回承诺。
答案 1 :(得分: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()
});