我有一组嵌套的ajax调用,类似于:
function getSubcategories(cat,callback) {
$.ajax({
url:'myurl.php',
data:'q='+cat,
dataType='json',
success:function(result){ callback(result) }
});
}
function getSubcatElements(subcat,callback) {
$.ajax({
url:'myurl2.php',
data:'q='+subcat,
dataType='json',
success:function(result){ callback(result) }
});
}
function organizeData(cat,callback) {
getSubcategories(cat,function(res){
totals=0;
list=new Array;
$.each(res['subcat'],function(key,val){
getSubcatElements(val,function(items){
$.each(items['collection'],function(key2,val2) {
list.push(val2['descriptor']);
});
totals+=items['count'];
// If I shove "totals" and "list" into an object here to callback, obviously gets called many times
}
// If I return an object here, it doesn't actually have counts from the asynchronous call above
}
function doStuff(cat) {
organizeData(cat,function() {
//stuff
});
所以我正在运行一个循环异步查询,它是另一个异步查询的子代,我希望子循环的最终结果不是“懒惰”。现在我只是返回更新的结果,所以数字改变了几次,但我想一下子做。
似乎显而易见的地方是将结果存储在异步中并在$.each()
之后返回它,但JavaScript是疯狂的并且嘲笑明显的事情。我觉得这应该涉及$.Deferred()
,但我发现的样本似乎都应该在第一次迭代后触发......
(这些功能是故意分开的,因为有时候只使用一个或仅使用另一个)。
提前致谢!
答案 0 :(得分:0)
首先,您应该在服务器端组织数据库查询,以便返回单个,多重复用的结果。而不是多次调用它。
除此之外,假设您在类别调用返回之前不知道要调用多少个子类别,最好的办法是创建一个全局变量,每次调用时都会计入,并且然后每次回调收到结果时倒计时。每当回调触发,倒计时,新计数为零时,请进行更新。
答案 1 :(得分:0)
现在,你的方法很好。我想在您的代码中添加以下更改
function organizeData(cat, callback) {
getSubcategories(cat, function(res) {
totals = 0;
list = new Array();
totalSubCatItem = res['subcat'].length;
currentSubCatItem = 0;
$.each(res['subcat'], function(key, val) {
getSubcatElements(val, function(items) {
$.each(items['collection'], function(key2, val2) {
list.push(val2['descriptor']);
});
totals += items['count'];
// If I shove "totals" and "list" into an object here to callback, obviously gets called many times
// Here the solution
currentSubCatItem++;
if(currentSubCatItem === totalSubCatItem){
callback(/** pass argument here **/)
}
});
// If I return an object here, it doesn't actually have counts from the asynchronous call above
});
})
}
function doStuff(cat) {
organizeData(cat, function( result) {
//stuff
console.log(result)
});
}