繁体   English   中英

多个 $http 上的 Angular 承诺

[英]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调用都成功了? 如果其中任何一个失败,将执行一些操作。

您也可以使用$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);
  })
}),

上面这基本上意味着执行整个请求并在所有请求都完成后设置行为。

在之前的评论中:

使用状态你可以知道是否有任何错误。 如果需要,您还可以为每个请求设置不同的配置(例如,可能超时)。

如果其中任何一个失败,将执行一些操作。

来自同样基于 A+ 规范的文档

$q.all(successCallback, errorCallback, notifyCallback);

如果您想解决第一个错误,那么您需要使您的 for 循环像这里一样同步Angular synchronous http loop to update progress bar

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;
});

如果您希望它是异步的,那么: 如何捆绑 Angular $http.get() 调用?

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/

接受的答案还可以,但仍然有点难看。 你有一系列想要发送的东西......而不是使用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循环,看起来也容易多了。 否则,它的行为与发布的其他示例相同,因此这纯粹是美学上的变化。

关于successerror一个警告词 - successerror更像是回调,并且警告您不知道承诺如何工作/未正确使用它。 Promises thencatch将链接并返回一个新的 Promise 封装到目前为止的链,这是非常有益的。 此外,使用successerror (除了$http的调用站点之外的任何其他地方)是一种味道,因为这意味着您明确依赖 Angular HTTP 承诺,而不是任何符合 A+ 的承诺。

换句话说,尽量不要使用success / error ——它们很少有原因,它们几乎总是表明代码异味,因为它们引入了副作用。


关于你的评论:

我在 $q.all 上做了我自己的非常简单的实验。 但它仅在所有请求成功时触发。 如果失败,则什么也不会发生。

这是因为all的契约是,如果每一个承诺都成功,它要么解决,要么如果至少一个承诺失败,则拒绝。

不幸的是,Angular 内置的$q服务只有all 如果您希望拒绝的承诺不会导致最终的承诺被拒绝,那么您将需要使用allSettled ,它存在于大多数主要的承诺库中(如 Bluebird 和 kriskowal 的原始Q )。 另一种选择是推出自己的(但我建议蓝鸟)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM