Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/429.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在forEach在Angular中完成后执行命令_Javascript_Angularjs_Asynchronous - Fatal编程技术网

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

Javascript 在forEach在Angular中完成后执行命令,javascript,angularjs,asynchronous,Javascript,Angularjs,Asynchronous,我在HTML中通过ng单击执行以下函数: vm.items = []; vm.moveItems = function() { angular.forEach(vm.items, function (item) { $http({ method: 'PUT', url: '/api/item_move/' + item.id} }).then(function(

我在HTML中通过ng单击执行以下函数:

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中的异步编程非常陌生,因此想知道解决这个问题最常用的方法是什么。

将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循环。

您可以这样做:

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

创建一个数组,在其中存储来自HTTP调用的承诺。之后调用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。

解决方案:

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

我认为这不管用,是吗?forEach中的请求将触发,代码将在请求实际完成之前继续重新加载,不是吗?这不起作用,因为HTTP调用需要一些时间才能完成。在请求完成之前调用vm.reload。编辑为添加$timeout调用,应该允许http调用完成。完美!我假设这是一个通用的JS解决方案。我看到Angular有一个$q构造函数。使用它还是使用简单的JS解决方案更好?@mart1n是的,它是ES6中添加的JS解决方案。$q也有可能看到使用$q更好。所以s/PROMITE/$q/是唯一的改变吗?@mart1n正是这样。