2017-08-04 151 views
0

我有被从ng-click在HTML中执行以下功能:执行命令完成角

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

回答

2

创建你来自哪里,你的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()

+0

完美!我认为这是一个普通的JS解决方案。我看到Angular有一个'$ q'构造函数。使用它还是使用纯JS解决方案更好? – mart1n

+0

@ mart1n是的,它是ES6中添加的JS解决方案。也可以使用'$ q'(请参阅https://docs.angularjs.org/api/ng/service/$q)最好使用'$ q'。 –

+0

那么'/ Promise/$ q /'是唯一的改变吗? – mart1n

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

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

+0

我不认为这工作,不是吗? forEach中的请求将被触发,代码将在请求实际完成之前继续重新加载,否? – mart1n

+0

由于HTTP调用需要一些时间才能完成,所以这不起作用。在请求完成之前调用vm.reload()。 –

+0

编辑为添加$超时呼叫,应允许http呼叫完成。 – rrd

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

它的作品,但它是不好的编码风格。 –

+0

@ D.Simon你是对的。你的答案更好。 –

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() }) 
}); 
相关问题