Angular js在使用foreach完成多个http调用后回调

时间:2016-07-13 12:54:04

标签: javascript angularjs

我发送多个HTTP调用来更新foreach循环内的项目,并在所有请求完成后需要回调。我找到this但没有帮助。

我的代码:

$q.all(_($scope.students.items).each(function(item) {
   $scope.student.update(); //this is an http call
})).then(function() {
   // I need a callback need here
   alert("complete"); //should be shown after all students get updated but it is
                      // called before all network calls got complete
});

这是通用更新功能

self.update = function(item, callback) {
   that.post(item, self.getUrl("update") , function(err, data) {
      if (self.formatter) {
         data = self.formatter(data);
      }
      callback(err, data);
   });
 };

有什么建议吗?

4 个答案:

答案 0 :(得分:1)

您错过return函数中的update()关键字,因为它必须返回一个承诺(当然,that.post()函数也必须返回一个承诺):

self.update = function(item, callback) {
   return that.post(item, self.getUrl("update") , function(err, data) {
      if (self.formatter) {
         data = self.formatter(data);
      }
      callback(err, data);
   });
 };

然后这应该有效:

var promises = [];
_($scope.students.items).each(function(item) {
   promises.push($scope.student.update());
})
$q.all(promises).then(function() {
   alert("complete");
});

答案 1 :(得分:1)

您也可以使用map

尝试此操作
$q.all(_($scope.students.items).map(function(item) {
  item.update();
})).then(function() {
  alert("complete");
});
  

我已使用以下代码段更新了此处的代码。我使用了一些返回简单承诺的方法。包括两种方法可以做到这一点。

  • 将promises推入数组并使用q.all
  • 将地图与q.all
  • 一起使用



angular.module('demoApp', []).controller('DemoController', function($scope, $q, $timeout) {
  var a = function() {
    var deferred = $q.defer();
    console.log('Executing a');
    deferred.resolve();
    return deferred.promise;
  };
  var b = function() {
    var deferred = $q.defer();
    console.log('Executing b');
    deferred.resolve();
    return deferred.promise;
  };
  var c = function() {
    var deferred = $q.defer();
    console.log('Executing c');
    deferred.resolve();
    return deferred.promise;
  };
  var f = [{
    call: a
  }, {
    call: b
  }, {
    call: c
  }];

  $scope.mapTest = function() {
    $q.all(f.map(function(item) {
      return item.call();
    })).then(function() {
      console.log("complete");
    });

  };
  $scope.promisePush = function() {
    var promises = [];
    angular.forEach(f, function(item) {
      promises.push(item.call());
    });
    $q.all(promises).then(function() {
      console.log('complete');
    });
  };


});

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="demoApp">
  <div ng-controller="DemoController">
    <button ng-click="mapTest()">Q.all using map</button>
    <button ng-click="promisePush()">Q.all using promise push</button>
  </div>
</body>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

$q.all(_.map($scope.students.items, function(item) {
   return item.update();
})).then(function() {
   //everything has completed
});

$scope.student.items中每个项目的更新功能必须返回此功能的承诺。类似的东西:

function update() {
   return $http( ... );
}

答案 3 :(得分:0)

你不应该在foreach中发送相同的ajax。这应该是单个ajax并且更新应该在回调中完成,因此发送一个类似“studentsUpdate”的ajax并作为响应在foreudenst收集和更新对象数据上做foreach。良好做法是减少ajax呼叫。