$ q.all带递归?

时间:2015-12-17 15:20:02

标签: javascript angularjs recursion q

我有一个函数进行递归调用。结构看起来像这样:

var getData = function(data){
  makeDbCall().then(function(response){
    if(response.something === someCondition){
      foreach(object in response)
        getData(object ); //calls itself over and over 
      }
    }
  )
}; 

一般的想法(避免偏离主题)是,比如,获取一个城市的所有酒店,这些酒店的所有房间,这些房间的所有家具等。正常的$ q.all foreach电话就像是this - 函数定义:

var promises = [];

然后返回$ q.all:

return $q.all(promises);

我的问题是我不知道从哪里返回$ q.all - 如果我从" getData"返回它,它会在递归的第一次迭代时返回,并且(如我理解)如果初始调用在新推出之前解析,则可能不包括后续迭代。

如果我在getData()通话后返回,我会遇到同样的问题,因为众所周知,除非我们推迟,否则javascript会继续而不等待通话。

我意识到这个问题很模糊,而且我的回答模糊不清。我只是想看看我是否遗漏了绝对基本的东西,或者这是不可能的。 (我确实知道如何以非常肮脏的方式做到这一点,但我真的很想以某种方式使用$ q.all)。

Here is the actual function that I am trying to wait for with call values changed for sake of example.

3 个答案:

答案 0 :(得分:1)

我通过嵌套承诺解决方案尝试了以下内容:

function getData(){
  return new Promise((resolve, reject)){
    for(let item of response){
      getData(item).then((res)=>{
        resolve(res);
      },(err)=>{
        reject(err);
      });
    }
  }
}

诀窍是每次都可以使用诺言。这样,只有当子节点被解析时,您才能获得顶级保证的分辨率,从而允许您进行异步递归。

答案 1 :(得分:1)

你可能做的一件事就是在原始的promises数组中链接promises,并使用map来获取数组中每个元素的promise,即考虑这个snipet

function getHotels(city) { return ajaxPromise ...  }
function getRooms(hotel) { ... } 
function getFurniture(room) { ... } 
function showUI(furniture) { ... }

getHotels(city).then(function(hotels) {
  return $q.all(hotels.map( h => getRooms(h)))
}).then(function(hotelRooms) {
  return $q.all(hotelRooms.map (hr => getFurniture(hr)))
}).then(showUI)

答案 2 :(得分:1)

对于初学者---

  

此方法已弃用

app.factory('json',function($q,$http){
    return function(files){
        var promises = [];
        angular.forEach(files, function(file){
            var deffered  = $q.defer();
            $http({
                   url : file,
                   method: 'GET'
            }).success(function(data){
                   deffered.resolve(data);
            }).error(function(error){
                   deffered.reject();
            });
            promises.push(deffered.promise);
        }) 
        return $q.all(promises);
    }
});

.success方法的.error$http方法已弃用。有关详细信息,请参阅AngularJS $http Service API Reference

首选方式是:

app.factory('json',function($q,$http){
    return function(files){
        var promises = [];
        angular.forEach(files, function(file){
            var promise =
                $http({
                       url : file,
                       method: 'GET'
                      })
            promises.push(promise);
        }) 
        return promises;
    }
});

然后,您可以单独处理每个返回的承诺或使用$q.all。请注意$q.all 无弹性。第一个被拒绝的承诺将跳过.then方法,只有.catch方法才能捕获第一个拒绝。

var promiseList = json(files);

$q.all(promiseList).then (function (responseList) {
     //executes only if all promises ok
     $scope.dataList = doSomethingWith(responseList);
}). catch (error) { function (error)
     //executes with first error
     //log error
});

单独处理承诺:

promiseList[0].then (function (result) {
                   //save data
                   $scope.dataList[0] = result.data;
            }).catch (function (error) {
                   //log error
            });

请注意,.then.catch方法返回的数据与.success.error方法不同。