使用$ http承诺进入foreach

时间:2016-01-13 03:05:53

标签: angularjs foreach promise angular-promise deferred

我正在尝试通过forEach在各种服务的响应中创建一个对象..而且我没有得到我需要的结果。 我知道我应该使用内部迭代承诺,但不知道怎么做..

修改

好吧..我需要做的就是将数据的对象填入$ foreach foreach .. http转换为迭代承诺,示例代码:

someservice1.getitem().then(function(){
   var dataInfo= {};
      angular.foreach(data, function(v, k){

         dataInfo[v]=[]
         someservice2.getitem2(k.data).then(function(data){

               datainfo[v].push(data)

         })
     })
$scope.dataInfo = datainfo;
})

所以不能很好地工作..我认为你可以通过使用promises解决但我无法做到。 我希望你的帮助

2 个答案:

答案 0 :(得分:2)

问题是,在$scope.dataInfo = datainfo;对象完成之前,最终datainfo 早期执行。您需要创建一个承诺,该操作可以安全地链接

finalPromise.then ( function (datainfo) {
    $scope.dataInfo = datainfo;
});

您可以通过以前的承诺返回链接来创建finalPromise

var service1Promise = 
    someservice1.getitem().then(function(data){
        var promiseList = [];
        angular.foreach(data, function(v,k){
            var p = someservice2.getitem2(k.data);

            p.then(function(data) {
                 //return key and data for chaining
                 return { key: k, data: data };
            }) .catch (function (error) {
                 //throw key and error to chain rejection
                 throw { key: k,  error: error };
            });
            //push to list
            promiseList.push(p);
         });
         //return $q.all promise for chaining
         return $q.all(promiseList);
});

finalPromise

链接创建service1Promise
var finalPromise = 
    service1Promise.then(function(fulfilledList) {
        var dataInfoObj = {};
        //assemble data info
        angular.forEach(fulfilledList, function (fulfilledItem) {
            dataInfoObj[fulfilledItem.key] = fulfilledItem.data;
        });
        //return datainfoObj for chaining
        return datainfoObj;
});

现在,您可以从finalPromise 将数据放在$scope

finalPromise.then ( function onFulfulled (datainfo) {
    $scope.dataInfo = datainfo;
}).catch (function onRejection (error) {
    console.log("finalPromise rejected");
    console.log(error.key);
    console.log(error.error);
});

请注意$q.all 不具弹性。如果任何承诺被拒绝,$q.all将在第一次拒绝后被拒绝。

有关链接承诺的更多信息,请参阅AngularJS $q Service API Reference -- chaining promises

答案 1 :(得分:1)

你正在使用angularjs,所以使用$q,对于promises中的promises数组,你可以使你的代码成为这样的代码:

// first add $q service to your controller, 

someservice1.getitem()
  .then(function(data){
    var dataInfo= {};
    var promises = angular.map(data, function(item, index){
      var promises2 = angular.map(item.data, function(iData){
        someservice2.getitem2(iData)
      })
      return $q.all(promises2).then(function(resultArray){
        dataInfo[index] = resultArray;
      });
    });
    return $q.all(promises).then(function(){
      console.log('all data are retrived...');
      $scope.dataInfo = datainfo;
    });
  });

在ES6中看起来更优雅:

let serviceCall2 = data => someservice2.getitem2(data);  // serviceCall2 is just a closure for someservice2.getitem2() call
someservice1.getitem()
  .then(data => {
    let dataInfo= {}, 
      promises = data.map((item, index) => {
        let promises2 = item.data.map(serviceCall2);
        return $q.all(promises2).then(resultArray => dataInfo[index] = resultArray);
      });
    return $q.all(promises)
      .then(() => {
        console.log('all data are retrived...');
        $scope.dataInfo = datainfo;
      });
  });