伙计们,
我们的项目规模迅速扩大,我想成为一名优秀的 JS 公民,并在为时已晚之前实施测试。我们正在使用带有 Backbone Layoutmanager 和 Handlebars 模板的 Backbone 创建我们的前端,我已经阅读了一些 关于如何使用Jasmine和 Jasmine-Jquery 和Sinon测试 Backbone 驱动的应用程序的优秀博客文章,所以我决定去吧。
但是,我们的设置有点不典型,因为我们使用 RequireJS 模块,使用 Layoutmanager 增强 Backbone,以及预编译 Handlebars 模板。我们正在按照这些库的创建者的建议异步预编译模板,在我意识到任何类型的异步 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);
}
});
解决方案是将异步逻辑包装在runs
其中waitFor
。
现在的问题是:我认为这不是一个最佳解决方案,因为它迫使我复制 app.js 只是为了包装异步调用。有没有更好的方法来解决这个问题?
如果还不够公平,希望其他人从这篇文章中学到东西。