我有一个函数进行递归调用。结构看起来像这样:
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)。
答案 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
方法不同。