サーバーにAJAXリクエストを実行するJSがあり、JSONを返します。次のようになります。
$.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
コールバックが実行されます。中止しない場合は、リクエストを通常どおり実行します。
私は何かひどく間違ったことをしていますか?もしそうなら、それを行うためのよりスマートな方法は何でしょうか? そうでない場合、キャッシュされた値を完了コールバックに戻すにはどうすればよいですか (または少なくとも失敗コールバックに戻すには)?