我有一个客户端JS应用程序需要加载模板来显示每个项目。让我们说他们是笔记。
问题出在异步部分。我无法使模板只加载一次。它会在每次注释调用render
函数时加载。
以下是一些代码:
var notes = [ {}, {}, {} ] // Some Note objects
notes.forEach( function( note ) {
render( note )
}
// Have some variable to hold the template
var template
// Now on the render function
function render( note ) {
// First, if the template exists, go straight to the next function
if ( template ) {
// The display function takes care of appending the note
// to the body after applying datas on the template
display( note )
}
else {
// loadTemplate just loads the template in an ajax request
// and executes the callback with the template as argument
loadTemplate( function( data ) {
// I fill in the template variable
template = data
// And I display the note since the template is available
display( note )
} )
}
}
所以在这种情况下它会加载模板的三倍,即使有一个检查来防止这种情况。我想这是因为这三个模板直接进入了else,但我怎么能阻止这个呢?
我不想使用同步ajax加载,因为这会冻结浏览器。
编辑:最后,我使用了@Managu的解决方案,略有修改。
我没有使用他的循环,而是使用了以下内容,更加优雅:
while ( backlog.length ) {
display( backlog.shift() )
}
答案 0 :(得分:2)
var loadTemplate = function() {
var promise = $.get( "/" );
loadTemplate = function() {
return promise;
};
return promise;
};
请注意,这里不需要jQuery,我只是写为伪代码。您可以使用任何提供延迟的库。
loadTemplate().then( function( data ) {
// I fill in the template variable
template = data
// And I display the note since the template is available
display( note )
} )
答案 1 :(得分:1)
也许在加载模板后需要保留积压工作?基本上是一个队列,以平滑由异步引起的阻抗不匹配。
var template;
var backlog;
function render(note)
{
if (template) {
// Template already loaded, just display.
display(note);
} else if (backlog) {
// Template being loaded, push work onto backlog.
backlog.push(note);
} else {
// Template not being loaded yet. Create backlog queue and launch request
// to load template.
backlog=[note];
loadTemplate(function(loaded_template) {
// Template finally came over the wire. Save it, and then
// work off the backlog.
template = loaded_template;
for (var note=backlog.shift();
backlog.length!=0;
note=backlog.shift())
{
display(note);
}
} );
}
}
答案 2 :(得分:0)
“我不想使用同步ajax加载,因为这会冻结浏览器。”
同步ajax只会在您尝试使用jQuery执行此操作时冻结浏览器。 Frame.js旨在解决与您一样的问题。使用Frame有多种方法可以解决此问题,但它们都涉及一定量的同步和异步混合。可能最简单的方法是:
Frame(function(next){
loadTemplate(next);
});
Frame(function(next, data){ // data here is the value passed to loadTemplate's callback
notes.forEach( function( note ) {
template = data;
display( note );
});
next();
});
如果您不确定模板是什么,并且每个音符可能相同或不同,那么您可以改为:
notes.forEach( function( note ) {
Frame(function(next){
loadTemplate(note.templateName, next); // next here is a callback to advance to the next Frame
});
Frame(function(next, template){
display( note, template );
next();
});
});
这会加载模板同步,但显示更新异步。