return 如何区别一个承诺?

difference in how to return a promise?

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

我正在构建一个报告套件,需要先加载一些先决条件才能生成报告 运行。我需要来自 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() 方法在所有返回的承诺都已解决之前不会触发,那么如果我的函数包装在延迟回调中与执行 "normally" 有什么不同?这只是一个时间问题,还是延迟对象的工作方式取决于它的创建方式?

您的 "working" 解决方案只是巧合地起作用,并没有真正按照您的想法行事。

当您遍历数据并填充 toDownload 数组时,您将使用值 undefined 填充它,因为您的 getTemplate 函数不会 return任何事物。你应该return一个承诺。

getTemplate = function(name) {
    return $.get(name, function(data) {
        report.templates[name] = data;
    });
},

至于

return $.Deferred(function(d) {...}).promise();

var d = $.Deferred(); ... return d.promise();

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