使用jquery ajax缓存代码时,jquery ajax中的回调无法正常工作

下面是我的代码和问题,如果任何ajax调用成功回调,缓存代码无法正常工作。

var localCache = { /** * timeout for cache in millis * @type {number} */ timeout: 30000, /** * @type {{_: number, data: {}}} **/ data: {}, remove: function (url) { delete localCache.data[url]; }, exist: function (url) { return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout); }, get: function (url) { console.log('Getting in cache for url' + url); return localCache.data[url].data; }, set: function (url, cachedData, callback) { localCache.remove(url); localCache.data[url] = { _: new Date().getTime(), data: cachedData }; if ($.isFunction(callback)) callback(cachedData); } }; $.ajaxPrefilter(function (options, originalOptions, jqXHR) { if (options.cache) { var complete = originalOptions.complete || $.noop, url = originalOptions.url; //remove jQuery cache as we have our own localCache options.cache = false; options.beforeSend = function () { if (localCache.exist(url)) { complete(localCache.get(url)); return false; } return true; }; options.complete = function (data, textStatus) { localCache.set(url, data, complete); }; } }); function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) { if (typeof (method) === 'undefined') { method = "GET"; } if (typeof (headers) === 'undefined') { headers = ""; } if (typeof (parameters) === 'undefined') { parameters = ""; } successHandler = typeof (successHandler) === 'undefined' ? function (data) {} : successHandler; errorHandler = typeof (errorHandler) === 'undefined' ? function (data) {} : errorHandler; return $.ajax({ method: method.toUpperCase(), url: url, // async: false, data: parameters, headers: headers, success: function (data) { console.log('hi'); successHandler(data, options); console.log('bye'); }, error: function (data) { $('.loader').hide(); errorHandler(data); }, }); } 

按照上面的代码成功运行ajax successHandler(data, options); 函数应该是触发器,但它不是由于上面的缓存处理程序代码。 我不知道为什么这不起作用。 如果我写一些简单的东西而不是回调函数它是有效的。 与数据表Ajax回调相同的问题。 我必须在我的项目中使用全局级别的上面的缓存处理程序,无论ajax请求是来自datatable还是来自任何其他来源。

以上缓存代码来自https://stackoverflow.com/a/17104536/2733203

正如聊天室中所讨论的,我在代码中做了一些更改:

 var localCache = { /** * timeout for cache in millis * @type {number} */ timeout: 30000, /** * @type {{_: number, data: {}}} **/ data: {}, remove: function(url) { delete localCache.data[url]; }, exist: function(url) { return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout); }, get: function(url) { console.log('Getting in cache for url ' + url); return localCache.data[url].data; }, set: function(url, cachedData, callback) { localCache.remove(url); localCache.data[url] = { _: new Date().getTime(), data: cachedData }; console.debug('caching data for '+url, cachedData); if ($.isFunction(callback)) callback(cachedData); } }; $.ajaxPrefilter(function(options, originalOptions, jqXHR) { if (options.cache) { var complete = originalOptions.complete || $.noop, url = originalOptions.url; //remove jQuery cache as we have our own localCache options.cache = false; options.beforeSend = function() { if (localCache.exist(url)) { console.log('using cache, NO QUERY'); complete(localCache.get(url)); return false; } console.log('sending query'); return true; }; options.complete = function(data, textStatus) { localCache.set(url, data, complete); }; } }); function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) { method = method || "GET"; headers = headers || {}; parameters = parameters || {}; return $.ajax({ method: method.toUpperCase(), url: url, cache: true, // async: false, data: parameters, headers: headers, success: successHandler, error: errorHandler, }); } handleAjaxRequests('/echo/json/', {p1: 'hey'}, null, 'POST', function(data){console.log('first success without cache', data);}); setTimeout(function(){ handleAjaxRequests('/echo/json/', {p1: 'hey'}, null, 'POST', function(data){console.log('success! with cache hopefully', data);}); }, 2000); 

在这里小提琴

  1. localCache方法中添加了一些日志以查看发生了什么。 从不使用缓存,因此我添加了缺少的cache:true选项
  2. beforeSend方法中添加了一些日志来监视缓存和查询之间的切换。 一切正常。
  3. 清理了参数null检查并删除了空function(){} (使用$ .noop()而不是btw。
  4. 现在是你问题的核心。 回调errorHandlersuccessHandler是参数。 $.ajax是异步的! 它意味着在执行的某个时刻,在进行此调用之后,您将无法确定该变量是否具有相同的值。 最简单的解决方案是直接引用函数,让jQuery进行范围管理。 最难的解决方案是将这些函数提供给ajax设置中的context选项,我不建议这样做。

现在,您使用的解决方案允许您在没有包装器方法的情况下直接调用$.ajax 。 你为什么不直接使用它? 更简单,更不容易出错


编辑 :我真的不喜欢上下文,所以有另一种选择。

 function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) { method = method || "GET"; headers = headers || {}; parameters = parameters || {}; return $.ajax({ method: method.toUpperCase(), url: url, cache: true, // async: false, data: parameters, headers: headers, success: (function(handler, opt) { return function( /*Anything*/ data, /*String*/ textStatus, /*jqXHR*/ jqXHR) { console.log('hi'); handler(data, opt); console.log('bye'); }; })(successHandler, options), error: (function(handler, opt) { return function( /*jqXHR*/ jqXHR, /*String*/ textStatus, /*String*/ errorThrown) { console.log('ouch'); handler(errorThrown); }; })(errorHandler, options), }); } 

你可以用这个众所周知的javascript技巧来定义函数 。

这里有新的小提琴。


编辑2 :如果你希望successHandler即使从缓存中运行也应该使用complete而不是success

 function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) { method = method || "GET"; headers = headers || {}; parameters = parameters || {}; return $.ajax({ method: method.toUpperCase(), url: url, cache: true, // async: false, data: parameters, headers: headers, complete: (function(handler, opt) { return function( /*Anything*/ data, /*String*/ textStatus, /*jqXHR*/ jqXHR) { console.log('hi'); handler(data, opt); console.log('bye'); }; })(successHandler, options), error: (function(handler, opt) { return function( /*jqXHR*/ jqXHR, /*String*/ textStatus, /*String*/ errorThrown) { console.log('ouch'); handler(errorThrown); }; })(errorHandler, options), }); } 

在这里小提琴 。