【问题标题】:AngularJS wait for all async calls inside foreach finishAngularJS 等待 foreach 中的所有异步调用完成
【发布时间】:2016-10-04 21:27:24
【问题描述】:

我正在使用 angular.forEach 循环遍历数组并调用非 angular ajax 库 (Trello client.js)。客户端确实有“成功”和“错误”回调,但不返回角度延迟。我想在所有 ajax 调用完成后执行一个函数。

我有以下代码:

$scope.addCards = function(listId)
            {
                var cardTitles = $scope.quickEntryCards[listId].split('\n');
                angular.forEach(cardTitles, function(cardTitle,key)
                {
                    Trello.post('/cards', {
                        name:cardTitle,
                        idList:listId
                    },function(){ }, function(){ });
                });
                //TODO: wait for above to complete...
                $scope.init($routeParams.boardId);  
                $scope.quickEntryCards[listId] = '';    
            };

在 //TODO 和回调函数中我能做什么,以便最后两行仅在所有帖子成功或失败后运行?

【问题讨论】:

    标签: javascript angularjs asynchronous trello


    【解决方案1】:

    使用 Angular 的 $q 服务的伪代码。

    requests = [];
    
    forEach cardTitle
       var deferred = $q.defer();
       requests.push(deferred);
       Trello.post('/path', {}, deferred.resolve, deferred.reject);
    
    $q.all(requests).then(function(){
        // TODO
    });
    

    【讨论】:

    • 我认为这让我朝着正确的方向前进,但 Trello.post 没有返回承诺。所以我需要挂钩他们使用的回调和一个角度承诺......
    • 有趣,我知道我在你的问题中错过了这一点。奇怪,因为它看起来会返回一个承诺。通过使用 $q.defer(),你可以做出任何承诺。我将在示例中添加伪代码。
    • 是的,做到了。 Trello 的 api 是异步的,只是不是角度承诺,所以它很好地填充(现在我知道如何去做了;)您可以通过直接传递 deferred.resolve 和 deferred.reject 作为 Trello 的成功和回调方法来缩短一点,如下所示: Trello.post('/path',{},deferred.resolve,deferred.reject);
    • 我相信您需要使用 requests.push(deferred.promise); 才能使其正常工作。否则,$q.all(requests).then(...) 将立即被调用。
    • 也可以用map代替forEach,每次都延迟返回
    【解决方案2】:

    对于那些寻找问题标题“AngularJS 等待 foreach 完成中的所有异步调用” 的答案的人,这里是实现它的通用方法,也使用 angular 的 $q 服务: p>

    $scope.myArray = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    var loopPromises = [];
    angular.forEach($scope.myArray, function (myItem) {
        var deferred = $q.defer();
        loopPromises.push(deferred.promise);
        //sample of a long-running operation inside loop...
        setTimeout(function () {
            deferred.resolve();
            console.log('long-running operation inside forEach loop done');
        }, 2000);
    
    });
    $q.all(loopPromises).then(function () {
        console.log('forEach loop completed. Do Something after it...');
    });
    

    这是一个有效的sample。

    【讨论】:

      【解决方案3】:

      看看异步库https://github.com/caolan/async。

      因此,您可以并行或串行运行所有异步函数,一旦所有函数完成,您的公共回调将被执行。

      async.parallel([
          function(){ ... },
          function(){ ... }
      ], callback);
      
      async.series([
          function(){ ... },
          function(){ ... }
      ]);
      

      希望对你有帮助。

      【讨论】:

      • async 的forEach/forEachSeries 不是更合适吗?
      【解决方案4】:

      简单地说,你可以这样做

      var jsonArray3=[];
      angular.forEach($scope.jsonArray1,function(value,key){
          angular.forEach(jsonArray2,function(v,k){
              if(v.id==value.id){
                  $scope.jsonArray3.push(v);
              }
          })
      })
      
      
      
      $q.all($scope.jsonArray3).then(function(data){
         console.log("data:",data);
      })
      

      【讨论】:

        【解决方案5】:

        你也可以使用map:

        var requests = cardTitles.map(function(title) {
          var deferred = $q.defer();
          Trello.post('/path', {}, deferred.resolve, deferred.reject);
          return deferred;
        });
        
        $q.all(requests).then(function() {
        
        });
        

        如果post 方法已经返回了一个promise:

        var requests = cardTitles.map(function(title) {
          return $http.post('/path/' + title, {});
        });
        
        $q.all(requests).then(function() {
        
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-03-16
          • 2021-11-13
          • 2011-10-04
          • 1970-01-01
          相关资源
          最近更新 更多