2017-09-01 10 views
1

以下は私のコードです。問題が発生した場合、キャッシュ・コードは正常に動作していません。上記のコードを1として以下の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);を実行した後に機能がトリガする必要がありますが、キャッシュハンドラコード上記にそれが原因ではありません。なぜこれが動作していないのか分かりません。コールバック関数ではなく単純なものを書くと、それは機能しています。 datatable Ajaxコールバックと同じ問題。 プロジェクトのグローバルレベルで上記のキャッシュハンドラを使用しなければならないのは、データテーブルや他のソースからのajaxリクエストではありません。キャッシュコードの上

私はあなたのコード内のいくつかの変更を加えましたチャットルームで議論したように、ここでhttps://stackoverflow.com/a/17104536/2733203

+0

は「ハイ」印刷ですか? – 82Tuskers

+0

@ 82Tuskers要求がキャッシュされていないときに印刷されます。要求がキャッシュされた後、それはhiを印刷しません。 –

+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にいくつかのログを追加しました起こっていることを確認する方法。キャッシュが使用されていないので、不足しているものを追加しました
  2. の中にいくつかのログを追加して、キャッシュとクエリの切り替えを監視しました。すべてうまく動作します。
  3. (引数はnullチェックをクリーンアップし、空function(){}を削除ところで代わり$.noop()を使用しています。今
  4. をして問題の核心。コールバックerrorHandlersuccessHandlerは引数です。$.ajaxは非同期である!それは実行のいくつかの点で意味、最も簡単な解決策は、関数を直接参照し、jQueryにスコープ管理をさせることです。最も難しい解決策は、これらの関数をcontextオプションに与えることですin ajax settings私はお勧めしません。

これで、使用しているソリューションでラッパーメソッドなしで$.ajaxを直接呼び出すことができます。なぜそれを直接使用しないのですか?単純で


エラーを起こしにくいEDIT:別の代替があるので、私は本当にコンテキストのが好きではないんです。

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.


EDIT 2:あなたはsuccessHandlerがキャッシュから取得した場合にも実行したい場合は、代わりに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 herecompleteを使用する必要があります。

関連する問題