0

我有一个需要加载模板来显示每个项目的客户端 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() )
}
4

3 回答 3

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 )
} )
于 2012-04-27T23:01:45.490 回答
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); 
            }
        } );
    }
}
于 2012-04-27T22:54:57.397 回答
0

“我不想使用同步 ajax 加载,因为这会冻结浏览器。”

如果您尝试使用 jQuery,同步 ajax 只会冻结浏览器。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();
    });
});

这将加载模板同步,但显示更新异步。

于 2012-04-27T23:08:36.330 回答