2013-02-19 85 views
1

我有一段JS的,做一個AJAX請求到我的服務器,它返回一些JSON緩存從AJAX數據。它看起來像這樣:返回通過延遲迴調

$.ajax({ 
    dataType: 'json', 
    type: 'GET', 
    localCache: true, 
    cacheTTL: 6, 
    url: url 
}).fail(function(jqXHR, textStatus, something) { 
    //Display error message 
}).done(function(data) { 
    //Do stuff with the data 
}); 

現在,我想什麼做的是緩存使用localStorage的客戶端的JSON,因此,如果緩存足夠新鮮,請求永遠不會實際發送,並且緩存被用來代替。我一直在使用Paul Irish的ajax-localstorage-cache插件來做到這一點,但不幸的是,它不支持延遲迴調,所以我盡我所能來修改它,以便它可以。

$.ajaxPrefilter(function(options, originalOptions, jqXHR) { 
    // Cache it ? 
    if (!Modernizr.localstorage || !options.localCache) return; 

    var hourstl = options.cacheTTL || 5; 

    var cacheKey = options.cacheKey || options.url.replace(/jQuery.*/,'') + options.type + options.data; 

    // if there's a TTL that's expired, flush this item 
    var ttl = localStorage.getItem(cacheKey + 'cachettl'); 
    if (ttl && ttl < +new Date()){ 
     localStorage.removeItem(cacheKey); 
     localStorage.removeItem(cacheKey + 'cachettl'); 
     ttl = 'expired'; 
    } 

    var value = localStorage.getItem(cacheKey); 
    if (value) { 
     //In the cache? So get it, apply done callback & abort the XHR request 
     // parse back to JSON if we can. 
     if (options.dataType.indexOf('json') === 0) value = JSON.parse(value); 

     //Pass value back to the done callback somehow... 

     // Abort is broken on JQ 1.5 :(
     jqXHR.abort(); 
    } else { 
     $.Deferred(function(defer) { 
      //If it not in the cache, we change the done callback, just put data on localstorage and after that apply the initial callback 
      if (jqXHR.done) { 
       jqXHR.realdone = jqXHR.done; 
      } 

      jqXHR.done(function(data) { 
       var strdata = data; 
       if (options.dataType.indexOf('json') === 0) strdata = JSON.stringify(data); 

       // Save the data to localStorage catching exceptions (possibly QUOTA_EXCEEDED_ERR) 
       try { 
        localStorage.setItem(cacheKey, strdata); 
        // store timestamp 
        if (! ttl || ttl === 'expired') { 
         localStorage.setItem(cacheKey + 'cachettl', +new Date() + 1000 * 60 * 60 * hourstl); 
        } 
       } catch (e) { 
        // Remove any incomplete data that may have been saved before the exception was caught 
        localStorage.removeItem(cacheKey); 
        localStorage.removeItem(cacheKey + 'cachettl'); 
        if (options.cacheError) options.cacheError(e, cacheKey, strdata); 
       } 

       if (jqXHR.realdone) jqXHR.realdone(defer.resolve); 
      }).fail(defer.reject) 
     }).promise(jqXHR); 
    } 
}); 

我遇到的問題是,我似乎無法弄清楚如何獲得緩存值回原來done回調。如果我做jqXHR.abort()fail回調將會運行,如果我不放棄,那麼它只會正常執行請求。

我在做一些非常錯誤的事情嗎?如果是這樣,那麼更聰明的方法是什麼?如果沒有,我怎樣才能將緩存的值返回到完成的回調(或至少讓它回到失敗回調)?

+0

您可能需要重新鏈接'$ .ajax'本身;儘管如此,瀏覽器緩存不應該足夠好嗎? – 2013-02-19 13:29:58

+0

對於這個特定的用例,瀏覽器緩存可能足夠好。但是我們希望將其用於其他類型的緩存,也可能不會。 – 2013-02-19 13:53:30

+0

你是說在安裝ajax-localstorage-cache插件時,'$ .ajax()'不返回Promise?如果沒有,那麼你需要聯繫插件的作者。 – 2013-02-20 02:16:34

回答

0

你可以考慮爲你的Ajax調用的包裝。因此,像:

$.myAjax = function(params,doneCb,failCb){ //doneCb: doneCallback 

    var data = getFromLocalStorage(params), 

    if(data) { 
     var dfd = $.Deferred(); 
     dfd.done(doneCb); 
    }else{ 
     dfd = $.ajax(params).done(function(resp){ 
       // add to localStorage 
       doneCb && doneCb(resp); 
      }).fail(failCb) 
    return dfd; 
}