2017-08-04 146 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() }) 
}); 
相關問題