在forEach之后执行命令在Angular中完成

时间:2017-08-04 06:11:43

标签: javascript angularjs asynchronous

我有以下函数从HTML中的ng-click执行:

vm.items = [];
vm.moveItems = function() {
    angular.forEach(vm.items,
        function (item) {
            $http({
                method: 'PUT',
                url: '/api/item_move/' + item.id}
            }).then(function(response) {
                Toast.success("Successfully moved item " + item.id);
                vm.reload();
            }, function (error) {
                Toast.error("Failed to move item " + item.id, error);
            });
    });
};

现在,问题是vm.reload()在每次成功响应之后执行,实际上如果在整个forEach完成后执行一次就足够了。我对JS中的异步编程很新,所以想知道最常用的解决方法是什么。

4 个答案:

答案 0 :(得分:2)

创建一个数组,用于存储HTTP调用的promise。然后调用Promise.all()方法。这允许你在所有承诺完成后做一些事情。

vm.items = [];
vm.moveItems = function() {
    var promises = [];
    angular.forEach(vm.items,
        function (item) {
            promises.push($http({
                method: 'PUT',
                url: '/api/item_move/' + item.id}
            }));
    });
    Promise.all(promises)
        .then(function() {
            vm.reload();
        });
};

修改:由于您使用的是AngularJS,因此您也可以执行$q.all()

答案 1 :(得分:0)

你可以这样做:

vm.items = [];
vm.moveItems = function() {
var i = 0 
    angular.forEach(vm.items,
        function (item) {
            $http({
                method: 'PUT',
                url: '/api/item_move/' + item.id}
            }).then(function(response) {
                Toast.success("Successfully moved item " + item.id);
                i++;
                if(i == vm.items.length{ // execute only when its the last loop of foreach
                     vm.reload(); 
                }

            }, function (error) {
                i++;
              if(i == vm.items.length{ // execute only when its the last loop of foreach
                     vm.reload(); 
                }
                Toast.error("Failed to move item " + item.id, error);
            });
    });
};

答案 2 :(得分:0)

解决方案:

vm.items = [];

vm.moveItems = function() {
    var promises = [];

    angular.forEach(vm.items , function(item) {

        var promise = $http({
            method: 'PUT',
            url: '/api/item_move/' + item.id}
        }).then(function(response) {
            Toast.success("Successfully moved item " + item.id);
        }, function (error) {
            Toast.error("Failed to move item " + item.id, error);
        });

        promises.push(promise);

   });

   $q.all(promises).then(function() { vm.reload() })
});

答案 3 :(得分:-1)

将vm.reload()移到forEach循环之外:

vm.items = [];
vm.moveItems = function() {
  this._$timeout(() => {

    angular.forEach(vm.items,
      function (item) {
        $http({
          method: 'PUT',
          url: '/api/item_move/' + item.id}
        }).then(function(response) {
          Toast.success("Successfully moved item " + item.id);
        }, function (error) {
          Toast.error("Failed to move item " + item.id, error);
        });
    });

  });

  vm.reload();
};

编辑添加$ timeout,应该给它足够的时间来完成foreach循环。