17

我有多个同时运行的 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

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

我能想到的最好的方法是将 data1 和 data2 保存为全局变量。然后有一个计数器变量,每次返回成功时计数。然后,在 counter==TOTAL_NUM_REQUESTS 调用类似 updateAll() 的函数,然后遍历所有全局变量并将它们放在需要去的地方。但这似乎很混乱并且容易出错。另外,这将是很多全局变量。

我理想中想要的是让成功处理程序在返回时休眠,然后在我将所有它们都计算为返回的条件下,向它们发送唤醒消息,它们可以恢复执行。这似乎是最干净的,但我不知道 javascriptland 中有这样的功能。

有人对此有任何巧妙的想法吗?

答案更新

感谢下面的李,我能够得到一个解决方案。我的解决方案看起来类似于他的下面。我构建了一个async分配给 $.ajax 调用的变量列表。最初,那些 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 ....
   }
};

arguments 对象需要做一些工作来弄清楚它是什么。这是一个二维数组(列表列表)。第一个索引表示对应于给定 ajax 请求的返回对象。这似乎是有序的,但最好让您的服务器返回您可以查找的内容并相应地编写一个 if/else 块。然后,在该给定元素中,该列表中似乎有 3 个元素。第一个是从服务器返回的值,即您想要的值。第二个总是一个 string success,你大概可以用它来检查调用是否有效。该列表中的第三个元素似乎是初始请求(尽管我不确定)。这对我没有用。

无论如何,我希望这对将来的某人有所帮助。再次感谢 Lee 为我指明了正确的方向。

4

3 回答 3

37

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

jQuery.when 文档

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 调用,你可以像这样使用“应用”:

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

$.when.apply(this, results).done(function() {
    ... use 'arguments' array to get results ...
});
于 2013-01-22T18:12:58.453 回答
0

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

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

于 2013-01-22T18:13:35.880 回答
-1

一个简单的解决方案是使用 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

于 2017-03-09T01:33:27.593 回答