#jquery #ajax #jquery-deferred
#jquery #ajax #jquery-отложенный
Вопрос:
Сразу после загрузки моего скрипта я делаю Ajax-запрос, чтобы получить некоторые переводы. Это всегда должно возвращаться после того, как документ готов, поскольку я загружаю свои скрипты внизу страницы, но мне все еще интересно, можно ли получить отложенный объект в состоянии готовности документа.
Таким образом, можно было бы убедиться, что и документ готов, и вызов Ajax успешно возвращен, прежде чем делать что-либо еще, например, вот так:
$.when( $.ajax('translations'), document.ready())
.then(function(){
// Start doing stuff here
});
Ответ №1:
Вы можете связать отложенный объект с документом, используя data(), и разрешить () его в вашем ready
обработчике. Таким образом, вы сможете использовать сохраненный отложенный объект с помощью $.when():
$(document).data("readyDeferred", $.Deferred()).ready(function() {
$(document).data("readyDeferred").resolve();
});
$.when($.ajax("translations"), $(document).data("readyDeferred"))
.then(function() {
// Start doing stuff here.
});
Комментарии:
1. Спасибо, просто и понятный. Вероятно, это также будет работать с глобальной переменной или чем-то подобным.
2. @Daff, безусловно. Я лично предпочитаю использовать
data()
вместо глобальной переменной, потому что это более гибко и позволяет избежать загрязнения глобального пространства имен.3. Педантичное замечание. Вообще нет причин сохранять переменную. Это нужно только на этапе настройки, поэтому используйте область закрытия:
(function() { var deferred = new $.Deferred(); $(function() { deferred.resolve(); }); $.when($.ajax('foo'), deferred).then(function() {}); })();
… Если вы используете локальные области, нет необходимости сохранять, просто позвольте замыканиям привязать его к вам…
Ответ №2:
Вот очищенная версия комментария ircmaxell:
(function() {
var doc_ready = $.Deferred();
$(doc_ready.resolve);
$.when(doc_ready, $.ajax('translations')).then(function() {
console.log("done");
});
})();
Редактировать
Некоторые пояснения, чтобы остановить неправильные изменения:
Передача функции объекту jquery (например, $(some_func)
) выполняется так же, как $(document).ready(some_func)
.
Следовательно, $(doc_ready.resolve);
строка является просто сокращением для чего-то вроде этого:
$(document).ready(function() {
doc_ready.resolve()
});
Ответ №3:
Попробуйте это:
$.when($.ajax('translations'), $.ready).then(function() {
// Start doing stuff here
});
Комментарии:
1. Обратите внимание, что на самом деле это не отложенный, но в любом случае у
$.ready
него естьpromise
метод.2. Нет, это еще не задокументировано: github.com/jquery/api.jquery.com/issues/205
Ответ №4:
Моя версия:
$.when(
$.Deferred(function() { $(this.resolve); }),
$.ajax('translations')).
then(function() { console.log("done"); });
Комментарии:
1. Мне нравится, как содержится отложенный. Одним из предложений было бы изменить порядок ваших отложенных запросов, чтобы первым аргументом вашей функции обратного вызова было любое значение, которое было разрешено для отложенного $.ajax.
Ответ №5:
Обновление для справки (2015):
Это доступно в текущих версиях jQuery:
$.when($.ready).then(...);
Также просто преобразовать в поток, используя highlandjs:
_($.when($.ready)).map(transform).pipe(output) // etc.
Комментарии:
1. Как упоминалось ранее, не задокументировано, что $.ready является отложенным подобным объектом. В 2016 году это все еще недокументировано.
2. В этой ссылке есть кое-что об этом: api.jquery.com/jQuery.ready/#jQuery-ready1
3. Да, это было добавлено в документацию по состоянию на март 2017 года
Ответ №6:
jQuery when
не является надлежащим обещанием. Вы можете принудительно преобразовать его в такой:
function documentReady() {
return Promise.resolve($.when($.ready));
}
Использование:
documentReady().then(function($) { ... });
Случается, что это разрешается с помощью $
, так что это тоже вроде как удобно.
Альтернативная реализация:
function documentReady() {
return new Promise(r => $(r));
}