民间,
我们的项目规模迅速扩大,我希望成为一名优秀的JS公民,并在为时已晚之前实施测试。我们正在使用Backbone与Backbone Layoutmanager和Handlebars模板创建我们的前端,我已阅读some excellent博客文章,介绍如何使用Backbone驱动的应用程序测试Jasmine与Jasmine-Jquery和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);
}
});
解决方案是将异步逻辑包装在runs
和waitFor
中。
现在提出问题: 我不认为这是一个最佳解决方案,因为它迫使我复制app.js只是为了包装异步调用。有没有更好的方法解决这个问题?
如果还不够公平,希望其他人从这篇文章中学习。
答案 0 :(得分:0)
我还没有找到避免重复app.js的解决方案。但是这个文件很少改变,所以这不是一个真正的问题。 然而,我对上面的异步处理做了一些改进,使其更加健壮:
waitsFor(function() {
return JST[path] && JST[path].__compiled__;
}, "loading template", 1000);
return JST[path];
然后可以移除行done(JST[path]);
。
测试现在运行得更稳定,之前由于模板加载不正确,它们有时会失败。
接受这个作为答案。