如何回报承诺的差异?

时间:2015-09-16 18:58:14

标签: jquery jquery-deferred

我今天早上正在开发一款应用,发现了一些有趣的东西......想知道是否有人能解释我所看到的行为。

我正在构建一个报表包,需要在报表运行之前加载一些先决条件。我需要来自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都已解决之前不会触发,为什么如果我的函数包含在延迟回调中而不是执行“正常”,它会有所不同?这只是一个时间问题,还是延迟对象的工作方式会有所不同,具体取决于它是如何创建的?

1 个答案:

答案 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();

它们完全相同,不应该有任何不同的表现。我会责怪巧合或方便的时机。