views:

297

answers:

5

I need to be able to control the order of items being processed in the $(document).ready event.
These are multiple controls, loaded from multiple files, all asking to be called in the ready event. They all start an async call to the server (AJAX). Only after they are all done, I need to do some extra work.

What would be the elegant solution for this?

+1  A: 

Depending on the rest of the page, doing that "extra work" in an $.ajaxStop handler might be a more elegant option.

However, it wouldn't be appropriate if the user is able and/or likely to trigger subsequent $.ajax() calls while those initial calls are in progress. In that case, their manually triggered calls may prolong the $.ajaxStop event further than intended.

Dave Ward
The problem I will have an unknown number if `$.ajaxStop` events, since the page has a dynamic number of these controls.
Ron Harlev
@Ron not necessarily true. $.ajaxStop only fires after _all_ ajax calls are complete. However, if one call completed before another one was able to run, then you would get two.
Alex Sexton
This would still be a problem. I can't be sure all requests started together. Or that none completed before all were started.
Ron Harlev
To be totally honest, at this point, you've reached a logical endpoint. There is provably no way you could know, based on no prior data, that all of your dynamic requests have started and completed. This is because the state of all requests that have already fired being complete (even though more are coming) is identical to the state where all requests actually fire and complete. This is essentially the Halting Problem: http://en.wikipedia.org/wiki/Halting_problem
Alex Sexton
yes. But I know all the requests stared by the time `ready` is done
Ron Harlev
Ok, then that doesn't get around the $.ajaxStop problem, but my solution, as long as it's run inside the `ready` block should avoid this problem.
Alex Sexton
If you set the $.ajaxStop handler before $(document).ready() (which you can), and then start all of the $.ajax() calls at $(document).ready(), the first completing quickly should not be an issue. Even testing locally, I don't think you'd ever run into that situation, since they're all going to begin at roughly the same time after the page renders. Keep in mind that even if you register $(document).ready() handlers throughout the page, they will all end up executing at about the same time in the end.
Dave Ward
You are absolutely correct, it would be a good move to run the $.ajaxStop handler before the `domready` event, and you could probably safely assume that you wouldn't run into the multiple `ajaxStop` edge case, event though it is a discrete possibility. Probably worth giving a shot.
Alex Sexton
A: 

Create variable that holds a value of 0. On the success function of each Ajax call increment that value by 1 and check if that value equals your total number of calls if it does execute your completeion function.

ctrlShiftBryan
@Shog9 your right. You could just use a variable since it would remain in scope the whole time.
ctrlShiftBryan
+1  A: 

John Resig on function evaluation order in $(document).ready:

Every time a new function is added to the queue, it's just being added to an array - then being popped back off again when executed. Let me know if this does not happen for you.

$.readyList - only in pre 1.4 versions

jQuery exposed a property called $.readyList, which is an array to allow function orded manipulation, however $.readyList in no longer publicly exposed in jQuery 1.4.0

Hackerish way

you can try $(window).load(function () {});, it should execute after the whole window has loaded (not when document is ready, as it is with $(document).ready()

Juraj Blahunka
Yes. but functions are being added to the queue from different controls on the page. I want to make sure something is being done last. Like a "finally" in a try catch.
Ron Harlev
I know about the `readyList`. I'm using 1.4.2
Ron Harlev
A: 

Do you want to "control all ready events" or "do something after all ajax calls"?

User Friendly
Do something after a multiple set of ajax calls that start in ready, coming from different controls on the page
Ron Harlev
+7  A: 

Asynchronous requests fire in order, but will return in whatever order they complete in first. So there is not a sure fire way to force them to end at the same time, however, you can build rules to only run code after certain groups have returned.

For instance, define a callback function with a set of rules, and pass it to each success callback for all of your ajax requests.

var completedObject = {};

function groupSuccessCallback() {
  // Test for any combination of requirements
  if ( completedObject.ajax1 && completedObject.ajax2 ) {
    ... // Do something that only requires 1 and 2
  }
  if ( completedObject.ajax1 && completedObject.ajax2 && completedObject.ajax3) { 
    ... // Do something that requires all 3 being done
        // your data is available at completedObject.ajax#
  }

  // Or test for _all_ entries for a dynamic count
  var allComplete = true;
  for(var i in completedObject) {
     if ( completedObject.hasOwnProperty(i) && !completedObject[i] ) {
       allComplete = false;
     }
  }

  // Do whatchya need.
  if (allComplete) { 
    alert("bb-b-bb-b-b-b-bbb... that's all folks!");
  }
}

Then set the flags inside of your success functions:

// Ajax1
completedObject['anything'] = false; // instantiate a dynamic entry in the object or use an array if you can't use names.
$.ajax({
  ...,
  ...,
  success: function(data) {
    completedObject['anything'] = data || true;
    groupSuccessCallback();
  }
});
Alex Sexton
This is interesting. But I have a **dynamic** number of controls that would start these async requests. I can't have a static `if`.
Ron Harlev
It's a minor code change... I'll update it.
Alex Sexton