如何从缓存或ajax加载返回模板?

时间:2016-02-01 17:29:14

标签: javascript jquery ajax deferred

在我的代码中,我尝试从缓存加载模板。如果缓存中没有模板 - 由ajax从服务器加载模板。加载完成后,我想将模板放入缓存并返回它。这是它:

var manager = function () {

    return {

        cache: [],
        getTemplate: function (templateId) {

            this.templateId = templateId;

            if (this.cache[this.templateId]) {
                return this.cache[this.templateId];
            }

            return this.loadTemplate();
        },

        loadTemplate: function() {

            var
            self = this;

            $.get('/assets/templates/' + this.templateId + '.html', function (templateHtml) {

                self.cache[self.templateId] = templateHtml;
                return self.getTemplate(self.templateId);
            });
        }
    }
}

var
manager = manager();

$('body').append( manager.getTemplate('template') );

我知道我的代码无效,因为ajax请求在函数loadTemplate结束后完成。我认为代码可以用延迟对象修复,但不知道如何。任何人都可以帮我找到解决方案吗?

3 个答案:

答案 0 :(得分:2)

实现目标有两种方法:

  1. Promises(有很多libs / shims)。我只是为了学习而将它重写为ES6:

    let manager = function () {
    
        return {
    
            cache: [],
    
            getTemplate(id) {
                let cache = this.cache;
    
                return new Promise((resolve, reject) => {
                    if (cache[id]) {
                        resolve(cache[id]);
                    } else {
                        this.loadTemplate(id)
                            .then(template => {
                                cache[id] = template;
                                resolve(template);
                            })
                            .fail(reject);
                    }
                });
            },
    
            loadTemplate(id) {
                return $.get('/assets/templates/' + id + '.html');
            }
        }
    };
    
    let manager = manager();
    
    manager.getTemplate('template').then((template) => {
        $('body').append(template);
    });
    
  2. 回调:

    let manager = function () {
    
        return {
    
            cache: [],
    
            getTemplate(id, cb) {
                let cache = this.cache;
    
                if (cache[id]) {
                    cb(cache[id]);
                } else {
                    this.loadTemplate(id)
                        .then(template => {
                            cache[id] = template;
                            cb(template);
                        });
                }
            },
    
            loadTemplate(id) {
                return $.get('/assets/templates/' + id + '.html');
            }
        }
    };
    
    let manager = manager();
    
    manager.getTemplate('template', (template) => {
        $('body').append(template);
    });
    

答案 1 :(得分:2)

以下是如何做到这一点,支持所有主流浏览器,以及缓存请求。这样,每个模板只能执行1个请求。 (其他答案只缓存响应)。



var Manager = function() {

   return {

      cache: [],

      getTemplate(id) {
         var that = this;

         if (that.cache[id] && that.cache[id].then){
            console.log("Promise cache");
            return that.cache[id]; //return promise from cache
         }

         return $.Deferred(function() {
            var def = this;
            
            if (that.cache[id]) {
               console.log("Retrieved from cache!");
               return def.resolve(that.cache[id]); //return cached template
            }

            that.cache[id] = def; //Cache promise
            
            console.log("Retrieving template...");
            that.loadTemplate(id).then(function(template) {
               that.cache[id] = template;
               def.resolve(template)
            }).fail(function() {
               def.reject();
            });

            return that.cache[id]; //return promise
            
         }).promise();

      },

      loadTemplate(id) {
         return $.get('https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js');
      }
   }
};

var manager = Manager();

manager.getTemplate('template').then(function(template){
   console.log("loaded 1");
});

//This will use the promise from the first call (1 Request only)
manager.getTemplate('template').then(function(template){
    console.log("loaded 2");
    manager.getTemplate('template').then(function(template){
       console.log("loaded 3"); //This will be retrieved fully from cache
    });
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

当您通过AJAX获取模板时,您将能够仅在AJAX成功中附加结果。所以你需要将追加逻辑作为回调传递。检查下面的代码。

var manager = function () {

    return {

        cache: [],
        getTemplate: function (templateId,callback) {

            this.templateId = templateId;

            if (this.cache[this.templateId]) {
                callback(this.cache[this.templateId]);
            }

            this.loadTemplate(callback);
        },

        loadTemplate: function(callback) {

            var
            self = this;

            $.get('/assets/templates/' + this.templateId + '.html', function (templateHtml) {

                self.cache[self.templateId] = templateHtml;
                callback(templateHtml)
            });
        }
    }
}

var
manager = manager();

manager.getTemplate('template',function(result) {

$('body').append( result );
});

您可能不需要2个功能来执行此操作。所以你可以把它作为一个