Объединение $.get и $.ready

Проще говоря, у меня есть вызов ajax, который иногда завершается до загрузки страницы, поэтому я попытался обернуть обратный вызов в $( fn ), но обратный вызов не срабатывает, если страница загружена... У кого-нибудь есть хорошее решение?

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

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

И да, я знаю, что если бы я перевернул их порядок, это всегда сработало бы, но тогда мои ajax-вызовы были бы без необходимости отложены до тех пор, пока документ не будет готов.


person Mark Kahn    schedule 10.04.2012    source источник
comment
Вы не пробовали это, не так ли?   -  person Bergi    schedule 10.04.2012
comment
@cwolves тот факт, что это не работает, является ошибкой в ​​$.ready. Это должно просто работать   -  person Raynos    schedule 10.04.2012
comment
@Raynos - Мех. Я использую более старую версию jQuery, потому что это уже существующий проект. Может придется залатать.   -  person Mark Kahn    schedule 10.04.2012


Ответы (6)


Нет, функции, добавленные в onDOMready, всегда будут выполняться, и будут выполняться мгновенно, если событие уже произошло. См. документы по адресу http://api.jquery.com/ready/: только если вы будете использовать $(document).bind("ready") оно не будет выполнено, если событие уже было запущено.

Возможной причиной того, что обработчики событий не срабатывают, являются другие обработчики, выдающие ошибку. jQuery имеет внутренний массив для обработчиков, которые должны быть выполнены, и метод, который обрабатывает собственное событие загрузки DOM, просто перебирает его. Если один из более ранних обработчиков вызывает ошибку, цикл прерывается, и другие обработчики, добавленные позже, не будут вызываться.

person Bergi    schedule 10.04.2012
comment
Это мило. Это не так :) точный код: ~function( $, RC ){ $.getJSON( 'json/financial-plan.json', function( accounts ){ console.log( 'step1' ); $( function(){ console.log( 'step2' ); $.replaceTmpl( 'financial_plan_template' ); WBR.initSection( '#financial-plan' ); } ); } ); }( jQuery, window.RazorCharts ); step1 всегда регистрируется. step2 иногда делает. - person Mark Kahn; 10.04.2012
comment
@cwolves, да, это они. Что-то еще не так с вашим кодом. jsfiddle.net/CpPR3 - person Alex Turpin; 10.04.2012
comment
@Bergi - это тот же код :) Просто указываю, что я не сделал ничего другого - person Mark Kahn; 10.04.2012
comment
@cwolves: Конечно, да, иначе это сработало бы :-) Дайте угадаю: вы добавляете другие обработчики загрузки где-то в свой код? - person Bergi; 10.04.2012
comment
@Bergi, нет, это ошибка в старой версии jQuery. Я исправил это, заменив готовую функцию на ту, которая немедленно запускает обратный вызов, если document.ready уже сработала, и теперь она работает. - person Mark Kahn; 10.04.2012

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

По сути, ajax попытается немедленно добавиться к someDiv, если это возможно. В противном случае он сохраняет результат ajax в result, а document.ready добавляет его самостоятельно при запуске. .off делается для предотвращения добавления данных дважды в случае, если ajax сделает это успешно. Это не должно иметь значения, поскольку в этом случае результат будет пустым, а просто чистым.

person Explosion Pills    schedule 10.04.2012
comment
Мне нравится этот ответ. Это именно то, для чего нужны пользовательские обработчики событий. - person Jeff B; 10.04.2012

Вот еще один метод, использующий deferreds. По-видимому, вы можете использовать deferreds с document.ready, просто это немного странно:

$(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);
   });
person Explosion Pills    schedule 10.04.2012

Загрузите ваши результаты в глобальную переменную и загрузите их в DOM-ready. Суть в том, что если результаты пусты, повторяйте с setTimeout до тех пор, пока они не будут пустыми.

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

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

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

Обратите внимание: вы можете добавить счетчик времени ожидания, чтобы прекратить попытки по истечении определенного времени, если ваш AJAX никогда не возвращает результаты по какой-либо причине.

person Jeff B    schedule 10.04.2012

Вам нужно будет проверить, готов ли dom внутри обратного вызова AJAX, чтобы убедиться, что вы собираетесь добавлять после готовности или сразу. см. ниже код,

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
});
person Selvakumar Arumugam    schedule 10.04.2012

Это не помешает сделать.

var getData;
$.get( '/foo.json', function( data ){
    getData = data;
});
$(function() {
    var intt = setTimeinterval(function() {
         if(getData.length) {
              //do your task
              clearInterval(intt);
         }
    }, 100);
});
person Starx    schedule 10.04.2012
comment
Что делать, если для завершения AJAX требуется более 100 мс после готовности DOM? Установить интервал всегда плохо в этих случаях... когда вы никогда не знаете, сколько времени потребуется для возврата ответа.. - person Selvakumar Arumugam; 10.04.2012
comment
@SKS, что ты имеешь в виду? Не будет проверки интервала после еще одного раунда 100 мс - person Starx; 10.04.2012
comment
@Statx мм .. мой плохой .. но все же не лучший способ справиться с этим делом. - person Selvakumar Arumugam; 10.04.2012