Angular 对多个 $http 的承诺
Angular promise on multiple $http
我正在尝试进行多次 $http
调用,我的代码如下所示:
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
我如何保证所有 $http
调用都成功?如果其中任何一个失败,将执行一些操作。
如果您希望在第一个错误时爆发,那么您需要像这里一样使您的 for 循环同步:
var data = ["data1", "data2", "data3", "data10"];
$scope.doneLoading = false;
var promise = $q.all(null);
angular.forEach(data, function(url){
promise = promise.then(function(){
return $http.get("http://example.com/" + data[i])
.then(function (response) {
$scope.data = response.data;
})
.catch(function (response) {
$scope.error = response.status;
});
});
});
promise.then(function(){
//This is run after all of your HTTP requests are done
$scope.doneLoading = true;
});
如果你希望它是异步的,那么:
app.controller("AppCtrl", function ($scope, $http, $q) {
var data = ["data1", "data2", "data3", "data10"];
$q.all([
for(var i = 0;i < data.length;i++) {
$http.get("http://example.com/" + data[i])
.then(function (response) {
$scope.data= response.data;
})
.catch(function (response) {
console.error('dataerror', response.status, response.data);
break;
})
.finally(function () {
console.log("finally finished data");
});
}
]).
then(function (results) {
/* your logic here */
});
};
这篇文章也不错:http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
您也可以使用 $q.all()
方法。
因此,根据您的代码:
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
你可以这样做:
var promises = [];
data.forEach(function(d) {
promises.push($http.get('/example.com/' + d))
});
$q.all(promises).then(function(results){
results.forEach(function(data,status,headers,config){
console.log(data,status,headers,config);
})
}),
以上基本上意味着执行所有请求并设置所有请求完成后的行为。
使用状态,您可以了解是否有任何错误。如果需要,您还可以为每个请求设置不同的配置(例如超时)。
如果其中任何一个失败,将执行一些操作。
From docs which are also based on A+ specs:
$q.all(successCallback, errorCallback, notifyCallback);
接受的答案还可以,但还是有点难看。你有一系列要发送的东西..而不是使用 for
循环,为什么不使用 Array.prototype.map
?
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
这变成了
var data = ['data1', 'data2', 'data3', ...., 'data10']
var promises = data.map(function(datum) {
return $http.get('http://example.com/' + datum)
})
var taskCompletion = $q.all(promises)
// Usually, you would want to return taskCompletion at this point,
// but for sake of example
taskCompletion.then(function(responses) {
responses.forEach(function(response) {
console.log(response)
})
})
这使用了高阶函数,因此您不必使用 for
循环,看起来也更容易上手。否则,它的行为与发布的其他示例相同,因此这纯粹是美学上的变化。
关于 success
和 error
的一个警告词 - success
和 error
更像是回调,是警告你不知道承诺是如何工作的/ 没有正确使用它。 Promise then
和 catch
将链接并且 return 一个新的 promise 封装了到目前为止的链,这是非常有益的。此外,使用 success
和 error
(除 $http
的调用站点以外的任何其他地方)是一种气味,因为这意味着您明确依赖 Angular HTTP承诺,而不是任何符合 A+ 标准的承诺。
换句话说,尽量不要使用 success
/error
- 很少有理由使用它们,它们几乎总是表明代码有味道,因为它们会引入副作用。
关于您的评论:
I have did my own very simple experiment on $q.all. But it only trigger when all request is success. If one if it fail, nothing happen.
这是因为 all
的合约是,它要么解决 如果 每个承诺都成功,要么拒绝 至少一个 失败了。
不幸的是,Angular的内置$q
服务只有all
;如果你希望拒绝的承诺不会导致结果承诺被拒绝,那么你将需要使用 allSettled
,它存在于大多数主要的承诺库中(比如 Bluebird 和 kriskowal 的原始 Q
)。另一种选择是自己动手(但我建议使用 Bluebird)。
我正在尝试进行多次 $http
调用,我的代码如下所示:
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
我如何保证所有 $http
调用都成功?如果其中任何一个失败,将执行一些操作。
如果您希望在第一个错误时爆发,那么您需要像这里一样使您的 for 循环同步:
var data = ["data1", "data2", "data3", "data10"];
$scope.doneLoading = false;
var promise = $q.all(null);
angular.forEach(data, function(url){
promise = promise.then(function(){
return $http.get("http://example.com/" + data[i])
.then(function (response) {
$scope.data = response.data;
})
.catch(function (response) {
$scope.error = response.status;
});
});
});
promise.then(function(){
//This is run after all of your HTTP requests are done
$scope.doneLoading = true;
});
如果你希望它是异步的,那么:
app.controller("AppCtrl", function ($scope, $http, $q) {
var data = ["data1", "data2", "data3", "data10"];
$q.all([
for(var i = 0;i < data.length;i++) {
$http.get("http://example.com/" + data[i])
.then(function (response) {
$scope.data= response.data;
})
.catch(function (response) {
console.error('dataerror', response.status, response.data);
break;
})
.finally(function () {
console.log("finally finished data");
});
}
]).
then(function (results) {
/* your logic here */
});
};
这篇文章也不错:http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
您也可以使用 $q.all()
方法。
因此,根据您的代码:
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
你可以这样做:
var promises = [];
data.forEach(function(d) {
promises.push($http.get('/example.com/' + d))
});
$q.all(promises).then(function(results){
results.forEach(function(data,status,headers,config){
console.log(data,status,headers,config);
})
}),
以上基本上意味着执行所有请求并设置所有请求完成后的行为。
使用状态,您可以了解是否有任何错误。如果需要,您还可以为每个请求设置不同的配置(例如超时)。
如果其中任何一个失败,将执行一些操作。
From docs which are also based on A+ specs:
$q.all(successCallback, errorCallback, notifyCallback);
接受的答案还可以,但还是有点难看。你有一系列要发送的东西..而不是使用 for
循环,为什么不使用 Array.prototype.map
?
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
这变成了
var data = ['data1', 'data2', 'data3', ...., 'data10']
var promises = data.map(function(datum) {
return $http.get('http://example.com/' + datum)
})
var taskCompletion = $q.all(promises)
// Usually, you would want to return taskCompletion at this point,
// but for sake of example
taskCompletion.then(function(responses) {
responses.forEach(function(response) {
console.log(response)
})
})
这使用了高阶函数,因此您不必使用 for
循环,看起来也更容易上手。否则,它的行为与发布的其他示例相同,因此这纯粹是美学上的变化。
关于 success
和 error
的一个警告词 - success
和 error
更像是回调,是警告你不知道承诺是如何工作的/ 没有正确使用它。 Promise then
和 catch
将链接并且 return 一个新的 promise 封装了到目前为止的链,这是非常有益的。此外,使用 success
和 error
(除 $http
的调用站点以外的任何其他地方)是一种气味,因为这意味着您明确依赖 Angular HTTP承诺,而不是任何符合 A+ 标准的承诺。
换句话说,尽量不要使用 success
/error
- 很少有理由使用它们,它们几乎总是表明代码有味道,因为它们会引入副作用。
关于您的评论:
I have did my own very simple experiment on $q.all. But it only trigger when all request is success. If one if it fail, nothing happen.
这是因为 all
的合约是,它要么解决 如果 每个承诺都成功,要么拒绝 至少一个 失败了。
不幸的是,Angular的内置$q
服务只有all
;如果你希望拒绝的承诺不会导致结果承诺被拒绝,那么你将需要使用 allSettled
,它存在于大多数主要的承诺库中(比如 Bluebird 和 kriskowal 的原始 Q
)。另一种选择是自己动手(但我建议使用 Bluebird)。