javascript Angular 将并行和链式请求与 $http.then() 和 $q.all() 结合使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20252640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular combining parallel and chained requests with $http.then() and $q.all()
提问by gregtczap
I have a rather complicated set of API calls to make and I'm attempting to do it as elegantly and performant as possible. I understand how to use the promise api of the $http
service to chain requests, and how to use the $q
service to make requests in parallel. But for this specific API workflow I need to do both.
我有一组相当复杂的 API 调用,我正在尝试尽可能优雅和高性能地完成它。我了解如何使用服务的promise api$http
来链接请求,以及如何使用$q
服务来并行发出请求。但是对于这个特定的 API 工作流程,我需要同时执行这两项操作。
Here is an example of the high-level API flow:
以下是高级 API 流程的示例:
/dog/<dog_id>
/breed/<breed_id>
/food/<food_id>
/cat/<cat_id>
/turkey/<turkey_id>
/fish/<fish_id>
/dog/<dog_id>
/breed/<breed_id>
/food/<food_id>
/cat/<cat_id>
/turkey/<turkey_id>
/fish/<fish_id>
The first tier of requests all have known ids. However the <breed_id>
required to make the /breed
call must be parsed from the /dog
response, and the <food_id>
required to make the /food
call must be parsed from the /breed
response. So /dog
, /breed
, and /food
all need to be chained. However /cat
, /turkey
, and /fish
can be made in parallel with the entire /dog
chain.
第一层请求都有已知的 ID。然而,<breed_id>
需要使/breed
呼叫必须从解析/dog
响应,并<food_id>
作出必要的/food
呼叫必须从解析/breed
响应。所以/dog
, /breed
, 和/food
都需要链接起来。但是/cat
,/turkey
, 和/fish
可以与整个/dog
链并行。
What I've got now (and it is working fine) are two separate sets of requests. How do I improve on this flow? Is there a way to combine the two stacks in a way that results in a single promise execution of .then()
?
我现在得到的(并且工作正常)是两组独立的请求。我如何改进此流程?有没有办法以导致单个承诺执行的方式组合两个堆栈.then()
?
var dogId = '472053',
catId = '840385',
turkeyId = '240987',
fishId = '510412';
var myData = {};
var firstSetComplete = false,
secondSetComplete = false,
returnData = function() {
if (firstSetComplete && secondSetComplete) {
console.log("myData.dog", myData.dog);
console.log("myData.dog.breed", myData.dog.breed);
console.log("myData.dog.food", myData.dog.food);
console.log("myData.cat", myData.cat);
console.log("myData.turkey", myData.turkey);
console.log("myData.fish", myData.fish);
}
};
// first call set
$http.get('http://example.com/dog/' + dogId)
.then(function(response) {
myData.dog = response.data;
return $http.get('http://example.com/breed/' + response.data.breed_id);
})
.then(function(response) {
myData.dog.breed = response.data;
return $http.get('http://example.com/food/' + response.data.food_id);
})
.then(function(response) {
myData.dog.food = response.data;
firstSetComplete = true;
returnData();
});
// second call set
$q.all([
$http.get('http://example.com/cat/' + catId),
$http.get('http://example.com/turkey/' + turkeyId),
$http.get('http://example.com/fish/' + fishId)
])
.then(function(responses) {
myData.cat = responses[0].data;
myData.turkey = responses[1].data;
myData.fish = responses[2].data;
secondSetComplete = true;
returnData();
});
回答by dtabuenc
You can pass in the first chain like so:
您可以像这样传入第一个链:
$q.all([
$http.get('http://example.com/cat/' + catId),
$http.get('http://example.com/turkey/' + turkeyId),
$http.get('http://example.com/fish/' + fishId),
$http.get('http://example.com/dog/' + dogId)
.then(function(response) {
myData.dog = response.data;
return $http.get('http://example.com/breed/' + response.data.breed_id);
})
.then(function(response) {
myData.dog.breed = response.data;
return $http.get('http://example.com/food/' + response.data.food_id);
})
.then(function(response) {
myData.dog.food = response.data;
return myData;
})
])
.then(function(responses) {
myData.cat = responses[0].data;
myData.turkey = responses[1].data;
myData.fish = responses[2].data;
secondSetComplete = true;
returnData();
});
That big chain of promises for dogs ends up returning a single promise that is resolved when the last then
is called and it's resolved with the result from that final function. So there is no reason that you can't nest it in your $q.all()
call.
这条大狗的承诺链最终会返回一个单一的承诺,该承诺在最后一个then
被调用时得到解决,并通过最终函数的结果得到解决。因此,您没有理由不能将其嵌套在您的$q.all()
通话中。