合并$ .get和$ .ready

Put simply I have an ajax call that sometimes completes before the page is loaded, so I tried wrapping the callback in $( fn ), but the callback doesn't fire if the page is loaded... Anyone have a good solution to this?

$.get( '/foo.json', function( data ){
    $( function(){
        // won't get here if page ready beats the ajax call

        // process data
        $( '.someDiv' ).append( someData );
    } );
} );

And yes, I know that if I flipped the order of those it would always work, but then my ajax calls would be needlessly deferred until the document is ready.

No, functions which are added to onDOMready will always be executed, and will instantly be executed if the event has already happened. See the docs at http://api.jquery.com/ready/: Only if you would use $(document).bind("ready") it will not get executed when the event had already fired.

A possible reason for non-firing event handlers are other handlers throwing an error. jQuery has an internal array for to-be-executed handlers, and the method which handles the native DOM load event just iterates over it. If one of the earlier handlers rises an error, the loop breaks and other handlers added afterwards will not be invoked.

Load your results into a global variable, and load them on DOM-ready. The key is that if the results are empty, iterate with setTimeout until they are not.

var result;
$.get("/foo.json", function(data) {
    result = data;
});

function insertAJAX() {
    if(result !== undefined) {
        $(".someDiv").append(result);
    } else {
        setTimeout(insertAJAX, 250);
    }
}

$(function() {
    insertAJAX();
});

Note, you could add a timeout counter to stop trying after a certain amount of time, in case your AJAX never returns results for whatever reason.

var result;
$(document).on('ready.specialAjax', function () {
   if (result) {
      $(".someDiv").append(result);
   }
});
$.get('/foo.json').done(function (data) {
   if ($(".someDiv").length) {
      $(".someDiv").append(data);
      $(document).off('ready.specialAjax');
   }
   else {
      result = data;
   }
});

Essentially, the ajax will try to append to someDiv immediately if it can. Otherwise, it stores the ajax result in result and document.ready appends it on its own when it runs. The .off is done to prevent the data from being appended twice in case the ajax does it successfully. This shouldn't matter since result would be blank in that case, but just to be clean.

You going to need to check if dom is ready inside AJAX callback to make sure if you going to append after ready or right away. see below code,

var isDomReady = false;

$.get( '/foo.json', function( data ){
    if (isDomReady) {
      $(function(){  $('.someDiv').append( someData );   });
    } else {
       $('.someDiv').append( someData );  
    }
} );

$(function(){
   isDomReady = true;
   // and all you ready code
});

It wont hurt to do this.

var getData;
$.get( '/foo.json', function( data ){
    getData = data;
});
$(function() {
    var intt = setTimeinterval(function() {
         if(getData.length) {
              //do your task
              clearInterval(intt);
         }
    }, 100);
});

Here is another method using deferreds. Apparently, you can use deferreds with document.ready, it's just a little odd:

$(document).data("readyDeferred", $.Deferred()).ready(function() {
   $(document).data("readyDeferred").resolve();
});
var jqxhr = $.get('/foo.json');
$.when(jqxhr, $(document).data('readyDeferred'))
   .done(function (jqxhr) {
      $(".someDiv").append(jqxhr[2].responseText);
   });