使用异步 Ajax 获取数据的记忆 Javascript 函数

Memoizing Javascript function that gets its data using asynchronous Ajax

假设我有获取模板的功能,如果模板以前从未使用过,它应该通过 AJAX 发送请求,然后是 return 模板,如果使用了模板,它应该是 return 来自缓存。

示例代码:

var getTemplate = (function(jQuery){
  //full template obj = {url: '', html: ''}
  var templates = {test: {url: '/templates/test.html'}};

  function getTemplate(templateId){
    if(templates[templateId].html){
      return templates[templateId];
    }

    jQuery.ajax({
      method: "get",
      url: templates[templateId].url
    }).success(function(respond){
      templates[templateId].html = respond;
    });

    //no idea what next...

    return getTemplate
  }
})(jQuery);

示例使用:

var template = getTemplate('test') 应始终 return /templates/test.html 内容

我不会使用 async: false 和任何框架。我不会学习该怎么做 ;)

在异步请求中,不可能return响应,因为getTemplate发送请求后已经立即完成,不会等待响应。

一个简单的解决方案是允许传递回调:

var getTemplate = (function(jQuery){
  //full template obj = {url: '', html: ''}
  var templates = {test: {url: '/templates/test.html'}};

  function getTemplate(templateId, callback){
    if(templates[templateId].html){
      callback(templates[templateId]);
    }

    jQuery.ajax({
      method: "get",
      url: templates[templateId].url
    }).success(function(respond){
      templates[templateId].html = respond;
      callback(templates[templateId]);
    });

  }

  return getTemplate;
})(jQuery);

用法:

getTemplate('test', function(template){
    console.log(template.html);
});

旁注:您遗漏了 return getTemplate; 这很重要。

由于您希望缓存模板并在已经可用的情况下立即解析它们,因此您需要确保 API 在这两种情况下保持一致。这意味着您的函数应该实现某种延迟或承诺接口。例如:

var getTemplate = (function(jQuery) {

    var templates = {
        test: {
            url: 'templates/test.html'
        }
    };

    return function(templateId) {

        if (templates[templateId].html) {
            return jQuery.when(templates[templateId].html);
        }

        return jQuery.ajax({
            url: templates[templateId].url
        })
        .then(function(responce) {
            templates[templateId].html = responce;
            return responce;
        });
    }
})(jQuery);

那么用法是:

getTemplate('test').done(function(html) {
    console.log(html);
});

演示:http://plnkr.co/edit/jutnHSQDAA4HLnmS0DqR?p=preview