Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting on multiple asynchronous calls to complete before continuing

So, I have a page that loads and through jquery.get makes several requests to populate drop downs with their values.

$(function() {     LoadCategories($('#Category'));     LoadPositions($('#Position'));     LoadDepartments($('#Department'));      LoadContact(); }; 

It then calls LoadContact(); Which does another call, and when it returns it populates all the fields on the form. The problem is that often, the dropdowns aren't all populated, and thus, it can't set them to the correct value.

What I need to be able to do, is somehow have LoadContact only execute once the other methods are complete and callbacks done executing.

But, I don't want to have to put a bunch of flags in the end of the drop down population callbacks, that I then check, and have to have a recursive setTimeout call checking, prior to calling LoadContact();

Is there something in jQuery that allows me to say, "Execute this, when all of these are done."?

More Info I am thinking something along these lines

$().executeAfter(     function () {   // When these are done         LoadCategories($('#Category'));         LoadPositions($('#Position'));         LoadDepartments($('#Department'));     },     LoadContact // Do this ); 

...it would need to keep track of the ajax calls that happen during the execution of the methods, and when they are all complete, call LoadContact;

If I knew how to intercept ajax that are being made in that function, I could probably write a jQuery extension to do this.

My Solution

;(function($) {     $.fn.executeAfter = function(methods, callback) {          var stack = [];          var trackAjaxSend = function(event, XMLHttpRequest, ajaxOptions) {             var url = ajaxOptions.url;              stack.push(url);         }          var trackAjaxComplete = function(event, XMLHttpRequest, ajaxOptions) {             var url = ajaxOptions.url;              var index = jQuery.inArray(url, stack);              if (index >= 0) {                 stack.splice(index, 1);             }              if (stack.length == 0) {                 callback();                 $this.unbind("ajaxComplete");             }         }          var $this = $(this);          $this.ajaxSend(trackAjaxSend)         $this.ajaxComplete(trackAjaxComplete)          methods();         $this.unbind("ajaxSend");     }; })(jQuery); 

This binds to the ajaxSend event while the methods are being called and keeps a list of urls (need a better unique id though) that are called. It then unbinds from ajaxSend so only the requests we care about are tracked. It also binds to ajaxComplete and removes items from the stack as they return. When the stack reaches zero, it executes our callback, and unbinds the ajaxComplete event.

like image 890
CaffGeek Avatar asked May 04 '10 19:05

CaffGeek


People also ask

How do you handle multiple asynchronous calls in node JS?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).

How do you wait for asynchronous function?

Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

What is an asynchronous call?

An asynchronous method call is a method used in . NET programming that returns to the caller immediately before the completion of its processing and without blocking the calling thread.

How long does async await wait?

Async Await makes execution sequential The above takes 100ms to complete, not a huge amount of time but still slow. This is because it is happening in sequence. Two promises are returned, both of which takes 50ms to complete.


1 Answers

You can use .ajaxStop() like this:

$(function() {   $(document).ajaxStop(function() {     $(this).unbind("ajaxStop"); //prevent running again when other calls finish     LoadContact();   });   LoadCategories($('#Category'));   LoadPositions($('#Position'));   LoadDepartments($('#Department')); }); 

This will run when all current requests are finished then unbind itself so it doesn't run if future ajax calls in the page execute. Also, make sure to put it before your ajax calls, so it gets bound early enough, it's more important with .ajaxStart(), but best practice to do it with both.

like image 171
Nick Craver Avatar answered Oct 11 '22 20:10

Nick Craver