Я все еще пытаюсь осмыслить deferred
и все остальное, поэтому помня об этом, я есть вопрос, как сделать следующее.
У меня и моей команды есть 3 отдельных метода .load ()
, каждый из которых берет определенный шаблон и добавляет его в один и тот же контейнер. Каждая загрузка занимает разное время, как вы могли подумать, поэтому, когда контент загружается, он загружается «ступенчато» (1, затем 2, затем 3). Я хотел бы использовать отложенные
объекты и подождать, пока они все не будут выполнены, а затем добавить их одновременно, чтобы удалить действие «ступенька».
$('').load(baseInfoTemplate, function () {
var baseData = {
// build some object
};
$.tmpl(this, baseData).appendTo($generalContainer);
});
Все три вызова являются аналогично вызову выше.
Как я могу этого добиться?
17
задан Chait 27 February 2017 в 22:48
поделиться
Вы можете сохранить promise objects
в массиве и использовать $.when()
, чтобы выяснить, выполнены ли эти обещания. Это может выглядеть так:
var templates = [ ];
function createPromise( baseInfoTemplate ) {
return $.Deferred(function( promise ) {
$('<div>').load(baseInfoTemplate, function() {
var baseData = { /* foobar */ };
templates.push( baseData );
promise.resolve();
});
}).promise();
}
var myPromises = [ ];
myPromises.push( createPromise( 'some data' ) );
myPromises.push( createPromise( 'even moar data' ) );
myPromises.push( createPromise( 'foo bar heay' ) );
$.when.apply( null, myPromises ).done( function() {
templates.forEach(function( template ) {
$.tmpl(this, template).appendTo($generalContainer);
});
});
Я использую здесь .apply()
, потому что он принимает массив в качестве аргументов для вызова функции. В общем, мы передаем все объекты обещания .when()
.
Пример : http://jsfiddle.net/Hg77A/1/
Обновление:
, как указал Альнитак Приведенный выше пример не будет иметь большого смысла, если не будет обработчика обратного вызова «success». Если достаточно просто запустить обработчик «все сделано» после передачи данных с помощью .load()
, вам просто нужно .resolve()
обещания в пределах success handler
из .load()
. Имеет ли это какой-то смысл?
Вот Gist для небольшого плагина jQuery, который добавляет функцию loadThen к набору элементов jQuery. Это в основном load () без обратного вызова и возвращает обещание, которое разрешается только после того, как контент загружен и вставлен в набор выбранных элементов.
Это в основном копирование / вставка собственного кода load () jQuery, за исключением того, что он возвращает обещание от фактического вызова ajax. Это позволяет вам получить отклоненное обещание в случае сбоя ajax.
Поскольку он основан на функциональности load (), вы можете добавить селектор после URL, разделенного пробелом, чтобы получить только фрагмент загруженного html.
Пример 1: Загрузить домашнюю страницу этого сайта в элемент с id = "container"
$('#container').loadThen('/').then(function () {
// loaded and ready.
}, function () {
// error
});
Пример 2: Загрузить Заголовок домашней страницы в заголовок этой страницы
$('h1').eq(0).loadThen('/ h1').then(function () {
// loaded and ready.
}, function () {
// error
});
Содержание:
(function ($) {
var _loadThen = $.fn.loadThen;
$.fn.loadThen = function (url, params) {
if (typeof url !== "string" && _loadThen) {
return _loadThen.apply(this, arguments);
}
if(this.length <= 0) {
return jQuery.Deferred().resolveWith(this, ['']);
}
var selector, type, response,
self = this,
off = url.indexOf(" ");
if (off >= 0) {
selector = jQuery.trim(url.slice(off));
url = url.slice(0, off);
}
if (params && typeof params === "object") {
type = "POST";
}
return jQuery.ajax({
url: url,
type: type,
dataType: "html",
data: params
}).then(function (responseText) {
self.html(selector ? jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector) : responseText);
return self;
});
};
}(jQuery));