在下面的简单示例中,我有一个方法调用(getMoreProducts
),需要在第一个方法调用(getProducts
)完成后调用。
由于我是angularjs的新手(并且对JS来说还是新手),我想确认是否有其他方法可以实现这一目标。我担心的是,如果需要在getMoreProducts
之后调用另一种方法,那么代码将是三级深度,依此类推。
.controller('ProductController',function(ProductService, $scope){
$scope.products = [];
$scope.moreProducts = [];
ProductService.getProducts().then(function(res){
$scope.products = res.data;
ProductService.getMoreProducts().then(function(res){
$scope.moreProducts = res.data;
});
});
对于此示例,假设ProductService
方法只是调用HTTP GET调用。
答案 0 :(得分:1)
OP中嵌套承诺中使用的反模式是一种“回调地狱”形式,这正是承诺应该帮助的形式。
当下次通话取决于之前的通话时,保证应该串联,这样它们的深度不会超过1级:
ProductService.getProducts().then(function (productsRes) {
$scope.products = productsRes.data;
return ProductService.getMoreProducts();
})
.then(function (moreProductsRes) {
$scope.moreProducts = moreProductsRes.data;
return ProductService.getEvenMoreProducts();
})
.then(function (evenMoreProductsRes) { ... });
当承诺不依赖于彼此的结果时(例如在这种情况下),它们可以并行执行,这就是$q.all
的用途:
$q.all([ProductService.getProducts(), ProductService.getMoreProducts()])
.then(function (responses) {
var productsRes = responses[0];
var moreProductsRes = responses[1];
$scope.products = productsRes.data;
$scope.moreProducts = moreProductsRes.data;
});
答案 1 :(得分:0)
是的,您可以利用承诺链。如果你在另一个中返回一个承诺,你可以避免讨厌的嵌套:
var app = angular.module('plunker', []);
// Before
app.controller('MainCtrl', function($scope, ProductService) {
$scope.name = 'World';
$scope.products = [];
$scope.moreProducts = [];
ProductService.getProducts().then(function(res){
$scope.products = res.data;
ProductService.getMoreProducts().then(function(res){
$scope.moreProducts = res.data;
});
});
});
// After with promise chaining
app.controller('MainCtrl', function($scope, ProductService) {
$scope.name = 'World';
$scope.products = [];
$scope.moreProducts = [];
ProductService.getProducts().then(function(res){
$scope.products = res.data;
return ProductService.getMoreProducts()
})
.then(function(res){
$scope.moreProducts = res.data;
});
});
app.service('ProductService', function($timeout){
this.getProducts = function() {
return $timeout(function(){
return {
data: [{name: 'Widget', color: 'blue'}]
}
}, 500)
}
this.getMoreProducts = function() {
return $timeout(function(){
return {
data: [{name: 'Widget', color: 'green'}, {name: 'Widget', color: 'red'}]
}
}, 1000)
}
})
根据getProducts
和getMoreProducts
调用的要求,您可以使用参数而不是使用不同的函数。
http://plnkr.co/edit/K4LPKWSD06QnwbRk8k0B?p=preview
编辑:
顺便说一句,我不推荐这种创建控制器和服务的方式,它只是默认的plunker模板。