AngularJS 中带有 Promise 的 $http 调用的条件链接
Conditional Chaining of $http-calls with Promises in AngularJS
我必须依次执行三个相互依赖的不同 $http 调用。到目前为止,我的工作解决方案是这样的
$http.get(".../1/...").success(function(){
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
});
现在需要做一些更改:如果条件为真,则应跳过第一次调用。我可以这样做:
if(skipCallOne) {
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
} else {
$http.get(".../1/...").success(function(){
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
});
}
这显然会导致大量代码复制。我发现如果我对特定的 $http 调用使用适当的函数,这可能会减少。但据我所知,更好的解决方案是正确使用和链接 $http-promises,如下所示:
$http.get(".../1/...").then(function(){
return $http.get(".../2/...");
}).then(function() {
return $http.get(".../3/...");
}).then(function() {
});
但现在我的问题是,如何有条件地跳过代码复制最少的第一次调用?
你可以试试这个方法:
$q.when(skipCallOne || $http.get(".../1/..."))
.then(function() {
return $http.get(".../2/...");
}).then(function() {
return $http.get(".../3/...");
}).then(function() {
});
您可以将 $http.get
调用包装在测试条件的函数中,并且 return 如果条件适用则 $http.get
承诺或如果条件不适用则包装预先解决的承诺。
function callOne() {
if(condition) {
return $http.get(".../1/...");
} else {
var deferred = $q.defer();
deferred.resolve();
return deferred.promise;
}
}
callOne().then(function() {
return $http.get(".../2/...");
})
我希望能够看到这样的东西在工作,所以我将这个小控制器放在一起来演示 promise 解析,首先是有条件的 $http.get 运行。我并不认为这与其他答案一样优雅或聪明,但我认为它与 Cristian 的解决方案非常相似。
注意:可能使这个问题难以理解的一件事是这个问题的答案经常显示 仅执行 的链接 $http 调用,为了简单起见,这些调用返回的值将被忽略,并且可能不会立即清楚如何分解事物以实际获得这些值。
app.controller('MainCtrl', function($scope, $q, $http) {
$scope.x = true;
var firstHttp = function() {
var deferred = $q.defer()
if($scope.x) {
data = 'x was true'
deferred.resolve(data);
} else {
$http.get('test.json')
.then(function(data) {
$scope.data1 = data;
deferred.resolve(data);
})
}
return deferred.promise
}
$scope.myGetterFn = function() {
firstHttp()
.then(function(data)
{
data.data ? $scope.data1 = data : $scope.datax = data;
$http.get('test2.json')
.then(function(data2)
{
$scope.data2 = data2
$http.get('test3.json')
.then(function(data3)
{
$scope.data3 = data3
})
})
})
}
});
我必须依次执行三个相互依赖的不同 $http 调用。到目前为止,我的工作解决方案是这样的
$http.get(".../1/...").success(function(){
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
});
现在需要做一些更改:如果条件为真,则应跳过第一次调用。我可以这样做:
if(skipCallOne) {
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
} else {
$http.get(".../1/...").success(function(){
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
});
}
这显然会导致大量代码复制。我发现如果我对特定的 $http 调用使用适当的函数,这可能会减少。但据我所知,更好的解决方案是正确使用和链接 $http-promises,如下所示:
$http.get(".../1/...").then(function(){
return $http.get(".../2/...");
}).then(function() {
return $http.get(".../3/...");
}).then(function() {
});
但现在我的问题是,如何有条件地跳过代码复制最少的第一次调用?
你可以试试这个方法:
$q.when(skipCallOne || $http.get(".../1/..."))
.then(function() {
return $http.get(".../2/...");
}).then(function() {
return $http.get(".../3/...");
}).then(function() {
});
您可以将 $http.get
调用包装在测试条件的函数中,并且 return 如果条件适用则 $http.get
承诺或如果条件不适用则包装预先解决的承诺。
function callOne() {
if(condition) {
return $http.get(".../1/...");
} else {
var deferred = $q.defer();
deferred.resolve();
return deferred.promise;
}
}
callOne().then(function() {
return $http.get(".../2/...");
})
我希望能够看到这样的东西在工作,所以我将这个小控制器放在一起来演示 promise 解析,首先是有条件的 $http.get 运行。我并不认为这与其他答案一样优雅或聪明,但我认为它与 Cristian 的解决方案非常相似。
注意:可能使这个问题难以理解的一件事是这个问题的答案经常显示 仅执行 的链接 $http 调用,为了简单起见,这些调用返回的值将被忽略,并且可能不会立即清楚如何分解事物以实际获得这些值。
app.controller('MainCtrl', function($scope, $q, $http) {
$scope.x = true;
var firstHttp = function() {
var deferred = $q.defer()
if($scope.x) {
data = 'x was true'
deferred.resolve(data);
} else {
$http.get('test.json')
.then(function(data) {
$scope.data1 = data;
deferred.resolve(data);
})
}
return deferred.promise
}
$scope.myGetterFn = function() {
firstHttp()
.then(function(data)
{
data.data ? $scope.data1 = data : $scope.datax = data;
$http.get('test2.json')
.then(function(data2)
{
$scope.data2 = data2
$http.get('test3.json')
.then(function(data3)
{
$scope.data3 = data3
})
})
})
}
});