我今天早上正在开发一款应用,发现了一些有趣的东西......想知道是否有人能解释我所看到的行为。
我正在构建一个报表包,需要在报表运行之前加载一些先决条件。我需要来自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()
方法在所有返回的promise都已解决之前不会触发,为什么如果我的函数包含在延迟回调中而不是执行“正常”,它会有所不同?这只是一个时间问题,还是延迟对象的工作方式会有所不同,具体取决于它是如何创建的?
答案 0 :(得分:1)
你&#34;工作&#34;解决方案只是偶然的工作,而不是实际做你认为它正在做的事情。
当您循环访问数据并填充toDownload
数组时,您需要使用值undefined
填充它,因为您的getTemplate
函数不会返回任何内容。你应该让它返回一个承诺。
getTemplate = function(name) {
return $.get(name, function(data) {
report.templates[name] = data;
});
},
至于
return $.Deferred(function(d) {...}).promise();
VS
var d = $.Deferred(); ... return d.promise();
它们完全相同,不应该有任何不同的表现。我会责怪巧合或方便的时机。