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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14465177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 13:36:24  来源:igfitidea点击:

multiple ajax calls wait for last one to load, then execute

jqueryajax

提问by Landon

I have multiple ajax queries running at the same time, and I want them to wait for the last one to return, and then run the success handler on all of the ajax calls. For a simplified example, consider:

我有多个 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

Let's say that all of the requests are sent off at the same time. As they are asynchronous, they will return at different times. Let's say one request takes 100ms to return and the other request takes 3000 ms to return. I obviously don't know which one will return first or last. They all update the DOM in some manner and I want those changes shown to the viewer all at once on one update. How do I do this?

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

The best I can think of is to save data1 and data2 as global variables. And then have a counter variable that counts every time a success is returned. Then, upon counter==TOTAL_NUM_REQUESTS call a function like updateAll(), then runs through all of the global variables and puts them where they need to go. But this seems messy and prone to errors. Plus that would be a lot of global variables.

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

What I ideally want is to have the success handlers sleep upon returning, and then on my condition of counting all of them as returned, send wake up messages to all of them and they can resume executing. This seems the cleanest, but I'm not aware of any functionality like this in javascriptland.

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

Does anybody have any slick ideas for this?

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

ANSWER UPDATE

答案更新

Thanks to Lee below, I was able to get a solution. My solution looked similar to his below. I build a list of asyncvariables that were assigned to the $.ajax call. Initially the success handler of those ajax calls were still being called, so I removed them and put them in another function that was to be subsequently called by this whenblock I wrote. I passed resultsin to the function like this:

感谢下面的李,我能够得到一个解决方案。我的解决方案看起来与下面的类似。我构建了一个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 ....
   }
};

The arguments object took a little work to figure out what it was. It was a 2d array (list of lists). The first index represented the returned object corresponding to a given ajax request. It seemsto be in order, but it would be best to have your server return something that you can look for and write an if/else block accordingly. Then, in that given element, there appears to be 3 elements within that list. The first being the value that was returned from the server, ie what you want. The second was always a string success, which you can presumably use to check if the call worked. And the third element in that list seems to be the initial request (though I'm not sure). This was of no use to me.

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

Anyway, I hope this helps somebody in the future. And thanks again to Lee to point me in the correct direction.

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

回答by Lee Meador

Use the jQuery $.when() function to run something when all the ajax calls finish:

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

jQuery.when docs

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

Added in response to questions:

在回答问题时添加:

If you have a bunch of ajax calls you can use 'apply' like this:

如果你有一堆 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 ...
});

回答by Scott S

This can probably be done in a very similar fashion to what you've already proposed.

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

First, create global variables var sleep = trueand var request_count = 0. Then start a timer that checks request_countagainst total number of requests every second or so. Then, your success functions can increment request_counterand then start looping until sleep == false. Then, when the monitoring function running via timer detects request_count == TOTAL_REQUESTSit sets sleep = false, and all your success functions continue about their business at that point.

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

回答by Jayadeep KM

A simple solution will be to use PreloaderQ module

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

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

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

Use as below

使用如下

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

The emptycallback will be called after both are finished

两者都完成后将调用 emptycallback