多个ajax调用等待最后一个加载,然后执行

时间:2013-01-22 18:07:02

标签: jquery ajax

我有多个ajax查询同时运行,我希望它们等待最后一个返回,然后在所有ajax调用上运行成功处理程序。有关简化示例,请考虑:

$.ajax({//ajax call 1
    url:page1.php,
    success: function(data1){
        //do something with data1
    }
});

....

$.ajax({//ajax call 2
    url:page2.php,
    success: function(data2){
        //do something with data2
    }
});
//consider more than just two concurrent requests

假设所有请求都是同时发送的。由于它们是异步的,它们将在不同的时间返回。假设一个请求需要100ms才能返回,另一个请求需要3000毫秒才能返回。我显然不知道哪一个会先返回。它们都以某种方式更新DOM,我希望在一次更新时一次性向观众显示这些更改。我该怎么做?

我能想到的最好的方法是将data1和data2保存为全局变量。然后有一个计数器变量,每次返回成功时都会计数。然后,在counter == TOTAL_NUM_REQUESTS调用updateAll()之类的函数时,然后运行所有全局变量并将它们放在需要的位置。但这似乎很乱,容易出错。加上那将是很多全局变量。

我理想的是让成功处理程序在返回时保持睡眠状态,然后在我将所有这些状态计数为返回的情况下,向所有这些程序发送唤醒消息并且它们可以继续执行。这似乎是最干净的,但我不知道在javascriptland中有这样的任何功能。

有人对此有任何光鲜的想法吗?

答案更新

感谢Lee,我能够得到一个解决方案。我的解决方案与他的下方类似。我构建了一个分配给$ .ajax调用的async变量列表。最初那些ajax调用的成功处理程序仍然被调用,所以我删除了它们并将它们放在另一个函数中,该函数随后由我编写的when块调用。我将results传递给了这样的函数:

var results = [];
results.push(async1);
results.push(async2);
... for all the results ...

$.when.apply(this, results).done(function() {
   for(var i=0;i<arguments.length;i++){
     dataobject=arguments[i][0]
     if(dataobject.variousattribute)
       mySuccessHandlerFirstGuy(dataobject)
     else if(dataobject.anotherattribute)
       mySuccessHandlerSecondGuy(dataobject)
       //etc ....
   }
};

参数对象花了一些时间来弄清楚它是什么。这是一个2d数组(列表列表)。第一个索引表示与给定的ajax请求相对应的返回对象。 似乎按顺序排列,但最好让您的服务器返回您可以查找的内容并相应地编写if / else块。然后,在该给定元素中,该列表中似乎有3个元素。第一个是从服务器返回的值,即您想要的值。第二个始终是字符串success,您可以使用它来检查呼叫是否有效。并且该列表中的第三个元素似乎是最初的请求(虽然我不确定)。这对我没用。

无论如何,我希望这有助于将来的某些人。再次感谢李指出正确的方向。

3 个答案:

答案 0 :(得分:34)

当所有ajax调用完成时,使用jQuery $ .when()函数运行:

jQuery.when docs

var async1 = $.ajax({//ajax call 1
    url:page1.php,
    success: function(data1){
        //do something with data1
    }
});

....

var async2 = $.ajax({//ajax call 2
    url:page2.php,
    success: function(data2){
        //do something with data2
    }
});

$.when(async2, async1).done(function(result2, result1) {
    ... do this when both are successful ...
});

在回答问题时添加:

如果您有一堆ajax调用,可以像这样使用'apply':

var results = [];
results.push(async1);
results.push(async2);
... for all the results ...

$.when.apply(this, results).done(function() {
    ... use 'arguments' array to get results ...
});

答案 1 :(得分:0)

这可能与您已经提出的方式非常相似。

首先,创建全局变量var sleep = truevar request_count = 0。然后启动一个计时器,每隔一秒左右检查一次请求的总数request_count。然后,您的成功函数可以递增request_counter,然后开始循环直到sleep == false。然后,当通过计时器运行的监控功能检测到request_count == TOTAL_REQUESTS时,它会设置sleep = false,并且您的所有成功功能将继续关于他们的业务。

答案 2 :(得分:0)

一个简单的解决方案是使用PreloaderQ模块

https://www.npmjs.com/package/preloaderq

使用如下

var preloader = new PreloaderQ()
preloader.setEmptyCallback(function(){
    //all tasks are finished
})

preloader.setFirstTaskCallback(function(){
    //started first task
})

preloader.enqueueTask('ajax1')

$.ajax({//ajax call 1
    url:page1.php,
    success: function(data1){
        prealoader.dequeueTask('ajax1')
        //do something with data1
    }
});

preloader.enqueueTask('ajax2')

$.ajax({//ajax call 1
    url:page2.php,
    success: function(data2){
        prealoader.dequeueTask('ajax2')
        //do something with data2
    }
});

两个完成后将调用emptycallback