JQuery call function when all AJAX requests are co

2020-06-24 08:33发布

问题:

My question is a variant of the question here

However, there are two differences:

  1. I don't know how many AJAX requests there are. For sure, there are at least 10. They run concurrently, or almost concurrently, and the number of requests changes every time.

  2. The function that I want to call makes AJAX requests as well. I don't want the AJAX requests to go on forever (which is what happened when I first tried). I only want this functionality one time.

Here is my code:

$("#calculateButton").ajaxComplete(function() {
    $(this).unbind();
    $(this).click();
});

So what I tried to do is attach the ajaxComplete callback to the calculate button. The problem is that this executes every time an ajax request finishes. Whereas what I want is for the function to execute when all AJAX requests are complete.

Is there any way to do this. When I write it out, it sounds convoluted. Should I just give up and create a hacky work-around?

回答1:

Use .ajaxStop() instead of your current method.

$("#calculateButton").ajaxStop(function() {
    $(this).unbind(); // $(this).unbind("ajaxStop") -> this is not needed as unbind will remove everything, but leaving it here as an FYI
    $(this).click();
});

http://api.jquery.com/ajaxStop/

Note: Updated code above to stop infinite loop.



回答2:

You should probably create some local variable that will be accessible form every request. Lets call it ajaxCount and assign 0 (zero) to it at the beginning.

For every request you want to count as the one that will block your function, increase ajaxCount by one. In callback executed when this particular request is finished (with error OR with success), decrease ajaxCount by 1 (one).

Also, within every callback mentioned above, just after you decrease ajaxCount, call another function, that will check whether ajaxCount equals to 0 (zero). If the test result is positive (meaning there is no AJAX request happening at this time), do what you wanted to do.

This is the basic idea, the implementation is rather simple. Please let me know if you have any problems regarding this.



回答3:

You can make use of deferred objects [docs] introduced in jQuery 1.5.

How to set this up depends on how you make the Ajax calls, but in general it is something like:

$.when(callAjaxA(), callAjaxB(), callAjaxC(), ...).then(callAjaxFinal);

where the callAjaxX functions would return the promise object returned by $.ajax. You can also easily add new calls via pipe [docs].

This will execute callAjaxFinal once all the request issued in callAjaxX are finished.