【问题标题】:Angular JS waiting for all the promises to be resolvedAngular JS 等待所有的承诺得到解决
【发布时间】:2017-05-25 01:09:30
【问题描述】:

我在一个数组上循环并对一个 api 进行异步调用返回的数据需要我与另一个数组合并当合并发生时所面临的问题某些承诺尚未解决,因此合并后的结果数组缺少数据。任何想法如何去做。 (我是 Angular 的新手)。 正在循环的数组至少有 200 个元素(我事先不知道数组的大小)我从每个元素中获取 id 并调用此服务:

for (i = 0; i < list.length; i++) {
     service.getRawHtml(list[i].service_object_id)
        .then(function(res){
            temp=htmlToArray(res);
            htmlDataList.push(temp);
    }, function(err){
         // error
    })
    }



service.getRawHtml=function (id){ 
   var defer = $q.defer();
        $http({
            method: 'GET',
            url: 'http://wlhost:50000/'+id
        }).success(function (response) {
            defer.resolve(response);
        }).error(function (data, status) {
            console.log("Failure");
            defer.reject(err);
    });
    return defer.promise;
}

提前致谢。

【问题讨论】:

  • 我在回答我的问题之前查看了问题,为我的问题提出的答案是类似的方法。但这与我面临的情况不同:)
  • 您的代码没有任何循环..?如果不是“您面临的相同场景”,也许您应该包含更多代码来说明您实际遇到的问题。
  • 该问题的重复,但我现在已经添加了我自己的答案,其中我还包括了一个修复所谓的deferred anti-pattern 你已经已实施。
  • 不客气!为了将来参考,最好包含太多代码而不是太少! ;)

标签: angularjs promise


【解决方案1】:

使用 $q.all - 来自documentation:

将多个承诺组合成一个承诺,当 所有输入的 Promise 都已解析。

示例用法:

    $q.all([
        getPromise(),
        getPromise(),
        getPromise() 
    ]).then(function(value) {
        $scope.result1 = value[0];
        $scope.result2 = value[1];
        $scope.result3 = value[2];
    }, function(reason) {
        $scope.result = reason;
    });

【讨论】:

  • 我刚刚更新了我的问题,我认为您建议的解决方案可能不适用于我的情况,但我会试一试
【解决方案2】:

正如@ndoes 建议的那样,这可以使用$q.all() 来完成,它接受一组承诺并在所有承诺都解决时解决,或者如果其中任何一个被拒绝则拒绝。

您在 for 循环中调用异步函数,该函数将执行,但一旦所有函数调用完成,代码将同步继续。所有承诺的解决都不会有任何神奇的等待。

您应该做的是将所有返回的 Promise 推送到一个数组,然后使用 $q.all() 等待它们。

//Declare an array to which we push the promises
var promises = [];

for (i = 0; i < list.length; i++) {
    //Call the service and push the returned promise to the array
    promises.push(service.getRawHtml(list[i].service_object_id));
}

//Await all promises
$q.all(promises)
    .then(function(arrayOfResults){
        //Use your result which will be an array of each response after
        //it's been handled by the htmlToArray function
    })
    .catch(function(err){
        //Handle errors
    });

我借此机会同时重构了您的代码,因为它正在实现deferred anti-pattern。因为$http 已经返回了一个promise,所以没有必要创建并返回一个新的promise。只需立即退回,就像

service.getRawHtml = function (id){ 
   return $http({
            method: 'GET',
            url: 'http://wlhost:50000/'+id
        }).success(function (response) {
            return htmlToArray(response);
        }).error(function (data, status) {
            console.log("Failure");
            $q.reject(error);
    });
}

【讨论】:

    【解决方案3】:

    只是为了澄清@nodes 解决方案:

    var promisesToWaitFor = [];
    for (i = 0; i < list.length; i++) {
        var promis = service.getRawHtml(list[i].service_object_id)
        promisesToWaitFor.push(promis)
    }
    $q.all(promisesToWaitFor).then(function(resultsArray) {
        var flatten = [].concat.apply([],resultsArray);
        temp=htmlToArray(flatten);
        htmlDataList.push(temp);
    }, function(err) {
        // error
    });
    

    【讨论】:

      猜你喜欢
      • 2014-03-12
      • 2020-10-17
      • 2022-01-17
      • 2021-02-02
      • 2017-04-04
      • 2019-09-23
      • 1970-01-01
      • 2019-04-29
      相关资源
      最近更新 更多