2017-09-01 69 views
1

下面是我的代碼和問題是與緩存代碼不能正常工作,如果任何ajax調用成功回調。回調在jquery ajax不工作時使用jQuery的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請求是從數據表或從任何其他來源。

上面的cache代碼是從這裏https://stackoverflow.com/a/17104536/2733203

+0

是'嗨'打印? – 82Tuskers

+0

@ 82Tuskers在請求沒有被緩存時打印。請求緩存後不打印嗨。 –

+0

也可以讓我們知道你是如何調用'handleAjaxRequests(...)'?另外,你能否在你的AJAX錯誤處理程序中輸入調試語句? – 82Tuskers

回答

2

由於在聊天室裏討論我做你的代碼的一些變化:

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

Fiddle here

  1. 增加了一些日誌在localCache方法來看看發生了什麼。緩存從不使用,因此我添加了缺少的cache:true選項
  2. beforeSend方法內添加了一些日誌以監視緩存和查詢之間的切換。一切正常。
  3. - 清理參數無效檢查和取出空function(){}(使用$.noop(),而不是BTW。
  4. 現在您的問題。該回調errorHandlersuccessHandler有觀點。$.ajax是異步的核心!這意味着在執行的某一點,在調用完成後,你不能確定變量是否具有相同的值。最簡單的解決方案是直接引用該函數並讓jQuery執行範圍管理。最難的解決方案是將這些函數賦予context選項在ajax settings裏我不推薦。

現在,您使用的解決方案允許您直接呼叫$.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伎倆又名currying功能。

New fiddle here.


編輯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), 
    }); 
} 

Fiddle here