1

サーバーに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コールバックが実行されます。中止しない場合は、リクエストを通常どおり実行します。

私は何かひどく間違ったことをしていますか?もしそうなら、それを行うためのよりスマートな方法は何でしょうか? そうでない場合、キャッシュされた値を完了コールバックに戻すにはどうすればよいですか (または少なくとも失敗コールバックに戻すには)?

4

2 に答える 2

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;
}
于 2013-02-19T23:18:45.430 に答える
0

これを試してください: http://www.artandlogic.com/blog/2013/06/ajax-caching-transports-compatible-with-jquery-deferred/

これにより、deferred を使用した ajax リクエストのキャッシュが可能になります。

于 2014-06-16T01:47:43.193 に答える