繁体   English   中英

$ q.all有递归吗?

[英]$q.all With Recursion?

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

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调用就是这样 -函数定义:

var promises = [];

然后返回$ q.all:

return $q.all(promises);

我的问题是,我不知道从哪里返回$ q.all-如果我从“ getData”返回$ q.all,则它将在递归的第一次迭代中返回,并且(据我所知)可能不包含后续迭代最初的呼叫会在新呼叫推送之前解决。

如果我在getData()调用之后将其返回,则会遇到相同的问题,因为众所周知,除非我们推迟执行,否则javascript会继续运行而不等待调用。

我意识到这个问题是含糊的,我的含糊答复完全可以。 我只是想看看我是否缺少绝对基本的东西,或者这是不可能的。 (我确实知道如何以一种非常肮脏的方式进行操作,但是我真的很想以某种方式使用$ q.all)。

这是我尝试等待的实际函数,为示例起见,更改了调用值。

我通过嵌套promise解析尝试了一些事情,如下所示:

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

诀窍是尽可能使用诺言。 这样,只有在解决孩子问题后,您才能获得最高级别的承诺,也可以进行异步递归。

您可能要做的一件事是在原始的Promise数组中链接Promise,并使用map来获取数组中每个元素的Promise,即考虑此片段

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)

对于初学者 - -

不推荐使用此方法

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);
    }
});

$http方法的.success.error方法已弃用 有关更多信息,请参见《 AngularJS $ http服务API参考》

首选方式是:

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 请注意, $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方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM