Сегодня утром я работал над приложением и нашел что-то интересное ... интересно, может ли кто-нибудь объяснить поведение, которое я вижу.разница в том, как вернуть обещание?
Я создаю набор отчетов, который требует загрузки некоторых предварительных условий до того, как отчеты будут запущены. Мне нужны мои данные из Firebase, и мне также нужно динамически загружать некоторые шаблоны Handlebars для отображения этих данных. Поскольку есть несколько страниц отчета, я сделал загрузку данных и шаблонов, используя отложенные объекты. Так что в моем reports.js
файл, у меня есть что-то вроде этого:
var report = {};
(function($) {
report = {
prefetchData : function() {
return $.Deferred(function(d) {
// get data
d.resolve();
}).promise();
},
prefetchTemplates : function() {
return $.Deferred(function(d) {
var templates = $.map($("[data-template]"), function(o) {
return $(o).data('template');
}),
getTemplate = function(name) {
$.get(name, function(data) {
report.templates[name] = data;
});
},
toDownload = [];
for (var i = 0; i < templates.lenght; i++) {
toDownload.push(getTemplate(templates[i]));
}
$.when.apply($, toDownload).done(function() {
d.resolve();
}).fail(function() {
d.reject();
});
}).promise();
}
};
})(jQuery);
Моя страница отчета сценарий выглядит следующим образом:
var report = report || {};
(function($) {
$.when(
report.prefetchData(),
report.prefetchTemplates()
).done(function() {
// load the charts, etc.
});
})(jQuery);
То, что я обнаружил, что карты начнут оказывать до шаблона был скачан, особенно если я запускал страницы в более медленной среде. Поэтому я изменил prefetchTemplates
функцию следующим образом:
prefetchTemplates : function() {
var d = $.Deferred(),
templates = $.map($("[data-template]"), function(o) {
return $(o).data('template');
}),
getTemplate = function(name) {
$.get(name, function(data) {
report.templates[name] = data;
});
},
toDownload = [];
for (var i = 0; i < templates.lenght; i++) {
toDownload.push(getTemplate(templates[i]));
}
$.when.apply($, toDownload).done(function() {
d.resolve();
}).fail(function() {
d.reject();
});
return d.promise();
}
Теперь, даже в самой медленной среде, мои шаблоны всегда загружена до того, графики начинают оказывать, что поведение я хочу. Поэтому мой вопрос: в чем разница между return $.Deferred(function(d) {...}).promise();
и var d = $.Deferred(); ... return d.promise();
? Иными словами, если основной метод .done()
не будет срабатывать до тех пор, пока все возвращенные обещания не будут решены, почему это имеет значение, если моя функция завершена в отложенном обратном вызове и выполняется «нормально»? Является ли это просто вопросом времени, или отложенный объект работает по-разному в зависимости от того, как он создан?
Я думаю, что вы забыли вернуть обещание от 'getTemplate', возможно, это ошибка копирования-вставки, потому что это сделало бы решение $ .when мгновенно, а не когда оно будет иметь данные. –
Но функция 'getTemplate' не предназначена для решения обещания; он просто предназначен для заполнения объекта report.templates. Разрешение должно выполняться в функции '$ .when()' после того, как все шаблоны будут сохранены. Разве я совершенно не понимаю, что вы говорите? – mounty
Если вы не вернетесь с getTemplate, то $ .when бесполезно, потому что, если ему не дают обещания подключиться, он просто разрешит мгновенно. Ваш текущий код в основном разрешает 'd' почти сразу. –