【问题标题】:Precompiling Handlebar templates with Backbone Layoutmanager for Jasmine tests使用 Backbone Layoutmanager 为 Jasmine 测试预编译 Handlebar 模板
【发布时间】:2012-12-04 18:53:11
【问题描述】:

乡亲

我们的项目规模正在迅速增长,我想成为一名优秀的 JS 公民,并在为时已晚之前实施测试。我们正在使用带有 Backbone Layoutmanager 和 Handlebars 模板的 Backbone 创建我们的前端,我已经阅读了 some excellent 博客文章,了解如何使用 Jasmine 和 Jasmine-Jquery 测试 Backbone 驱动的应用程序和Sinon,所以我决定去。

但是,我们的设置有点不典型,因为我们使用 RequireJS 模块、使用 Layoutmanager 增强 Backbone 以及预编译 Handlebars 模板。我们正在由这些库的创建者异步预编译模板as is suggested,在我意识到任何类型的异步 jQuery/Ajax 调用都不起作用之前,我花了一整天的大部分时间敲打我的头使用 Jasmine 运行应用程序。 试图使 $.ajax(...) 调用与 async: false 同步并没有这样做,并且深入研究 Layoutmanager JS 源代码,我发现这一切都是异步发生的。

无论如何,这就是我最终使预编译工作的方式:

Backbone.LayoutManager.configure({
    manage: false,

    prefix: "app/templates/",

    fetch: function(path) {
        var done;
        var that = this;

        // Concatenate the file extension.
        path = path + ".html";

        runs(function() {
            if (!JST[path]) {
                done = that.async()

                return $.ajax({ url: app.root + path, async: false }).then(
                    //Successhandler
                    function(contents) {
                        JST[path] = Handlebars.compile(contents);
                        JST[path].__compiled__ = true;
                        done(JST[path]);
                    },
                    //Errorhandler
                    function(jqXHR, textStatus, errorThrown) {
                        //Feil ved lasting av template
                        //TODO logg feil på en eller annen måte
                    }
                );
            }
            // If the template hasn't been compiled yet, then compile.
            if (!JST[path].__compiled__) {
                JST[path] = Handlebars.compile(JST[path]);
                JST[path].__compiled__ = true;
            }
        });

        waitsFor(function() {
            return done;
        }, "loading template", 500);
        return JST[path];
    },

    // Override render to use Handlebars
    render: function(template, context) {
        return template(context);
    }

});

解决方案是将异步逻辑包装在 runswaitFor 中。

现在回答问题: 我不认为这是一个最佳解决方案,因为它迫使我复制 app.js 只是为了包装异步调用。有没有更好的方法来解决这个问题?

如果还不够公平,希望其他人从这篇文章中吸取教训。

【问题讨论】:

    标签: javascript unit-testing templates backbone.js jasmine


    【解决方案1】:

    不幸的是,我还没有找到避免重复 app.js 的解决方案。但是该文件很少更改,因此这不是真正的问题。 不过,我对上面的异步处理做了一些改进,使其更加健壮:

        waitsFor(function() {
            return JST[path] && JST[path].__compiled__;
        }, "loading template", 1000);
        return JST[path];
    

    然后可以删除行done(JST[path]);

    现在测试运行更稳定了,以前它们有时会因为模板加载不正确而失败。

    接受这个作为答案。

    【讨论】:

    • 最近遇到了类似的问题,不确定您是否看到:github.com/tbranyen/boilerplate-handlebars-layoutmanager/blob/… 我最终使用了它的变体,但我的所有模板都作为开发过程的一部分进行了预编译,因此它们都在一个文件中(compiled-templates.js) 并通过 require 作为依赖项加载。您确实需要在返回 val 之前设置 compiled = true。如果由于任何原因没有将任何文件添加到预编译包中,您可以保留单个文件 ajax 编译以确保故障安全。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 2012-04-10
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    相关资源
    最近更新 更多