【问题标题】:Async template loading - How to load it only once?异步模板加载 - 如何只加载一次?
【发布时间】:2012-04-27 22:34:22
【问题描述】:

我有一个客户端 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() )
}

【问题讨论】:

  • .lodaTemplate 怎么知道要加载什么模板?
  • 因为这个应用程序中现在只有一个模板可以加载。

标签: javascript ajax templates


【解决方案1】:
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 )
} )

【讨论】:

    【解决方案2】:

    也许会保留在加载模板后需要完成的工作积压?基本上是一个队列来平滑由异步引起的阻抗不匹配。

    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); 
                }
            } );
        }
    }
    

    【讨论】:

    • 这不会改变模板将被多次加载的事实。第二个注释到函数的时候,由于template还是空的,所以会再次请求获取模板...
    • 哦,不错!让我试试然后回复你:) 不是很优雅 :(
    • shrug 原始 JavaScript,不涉及库。如果经常使用,将模式包装到库中(例如 Deferred 概念)当然是有意义的。
    • 如果您指的是我的回答,优雅不一定是延迟,而是客户端代码可以像以前一样简单干净,而 loadTemplate 正在做脏活
    • 好的,将您的答案标记为最佳 :-)。我已经编辑了我的答案,以向您展示我使用的内容,而不是您的 for 循环,这非常不雅:p
    【解决方案3】:

    “我不想使用同步 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();
        });
    });
    

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

    【讨论】:

    • 看起来 Frame.js 只是另一个延迟库:)。这确实回答了这个问题,但@Esailija 已经提出了这个。感谢您的努力!
    猜你喜欢
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多