web-dev-qa-db-ja.com

JavascriptでAjax応答をキャッシュするための可能なテクニックは何ですか?

XHRオブジェクトを介してjavascriptファイルをロードするJavascriptモジュールマネージャーを実装しています。このメソッドの問題は、リソースのキャッシュです。

  • まず、XHRは組み込みのブラウザキャッシュメカニズムに依存していますが、これは問題ありませんが、その動作はブラウザの実装によって異なります。
  • また、localStorageがあり、ダウンロードしたスクリプトをキャッシュするためにlocalStorageを使用する basket.js があります。問題は、通常5である限られたサイズのストレージにあります。 10MB。さらに、localStorageは、データの保存にも使用する多くのスクリプトの共有場所です。
  • そして、CacheAPIのServiceWorkerインターフェースがありますが、それはServiceWorkerランタイムでのみ利用可能であるため、私のニーズに間違いなく適合します。

彼がプロジェクトで使用している、または聞いたことがある、スマートな古いまたは新しいjavascriptキャッシングテクニックを知っている人はいますか?

:jQueryの使用を提案しないでください.ajaxは、XHRへのインターフェース、または組み込みのJavascript機能へのインターフェースを実装するその他のライブラリです。

編集:いくつかの貴重な提案がありました:

  • LocalForageというライブラリを使用します。ライブラリは、IndexedDB、WebSQL、およびlocalStorageへの統合APIを表し、どちらが使用されるかはブラウザによって異なります。
  • スペースに大きな制限がない、真に強力なストレージであるIndexedDBを使用してください。唯一の懸念は、最新のブラウザのみがIndexedDBを実装していることです。
16
Eugene Tiurin

これはJQUERYに固有です..。

Ajaxをキャッシュとして設定できます。

    $.ajaxSetup({ cache: true});

また、特定の呼び出しでキャッシュされた応答を行いたくない場合は、

 $.ajax({
        url: ...,
        type: "GET",
        cache: false,           
        ...
    });

反対(特定の呼び出しのキャッシュ)が必要な場合は、最初にfalseを設定し、特定の呼び出しにtrueを設定できます

Ajax応答の結果を保存したい場合は、ローカルストレージを利用できます。最新のブラウザはすべて、ストレージAPIを提供します。それら(localStorageまたはsessionStorage)を使用してデータを保存できます。

あなたがしなければならないのは、応答を受け取った後、それをブラウザストレージに保存することです。次に同じ通話を見つけたときに、応答がすでに保存されているかどうかを検索します。はいの場合、そこから応答を返します。そうでない場合は、新たに電話をかけます。

Smartjaxプラグイン 同様のことを行います。ただし、要件は呼び出し応答を保存することだけなので、jQueryajax成功関数内にコードを記述して応答を保存できます。また、電話をかける前に、応答がすでに保存されているかどうかを確認してください。

6
Somnath Muluk

Indexeddbはクライアント側でデータを格納するために使用されるメソッドであるため、インデックス付きデータベースクエリを許可します。

そしてこれはサポートされているブラウザです http://caniuse.com/#feat=indexeddb

そしてこれが唯一の問題です

Firefox (prior to version 37) and Safari do not support IndexedDB inside web workers.
Not supported in Chrome for iOS or other iOS WebViews.

Chrome 36 and below did not support Blob objects as indexedDB values.

これはあなたが試すことができる別の同様のポリフィルです 、しかし私の(限定的ではありますが)経験では、両方のポリフィルはバグがあり/不完全です。どちらも、問題を報告している人々のGitHubに多くの未解決の問題があります。そして、そのうちの1つをテストしたとき(どれを忘れたか)、ネイティブのIndexedDBよりも大幅に低速でした。

まともなポリフィルを作成することは可能かもしれませんが、現在のものは仕事をしていないようです。

非推奨になったWebSQLを使用する必要がありますか?

WebSQLの問題は、IEまたはFirefoxでサポートされないことです。少なくともFirefoxOSまたはWindowsPhoneが大きな市場シェアを獲得するまでは、モバイルブラウザのみをターゲットにしている場合は、おそらくWebSQLを使用することはできません。

サポートされていないすべてのブラウザーで、将来的にIndexedDBをサポートする予定はありますか?

はっきりさせておきましょう。他の誰もが最新のブラウザでIndexedDBをサポートしているので、あなたはAppleについて質問しています(iOS ChromeはAppleのレンダリングエンジンを使用します。Appleは他に何もさせないからです)。

AppleはIndexedDBをサポートしていないだけでなく、それについて公に何も言っていません(私が知る限り...そして私はかなりの量の検索を行いました)。これはかなり奇妙に思えます。したがって、私が知る限り、AppleがIndexedDBをサポートする予定があるかどうかは誰にもわかりません。私の陰謀論者は、HTML5アプリを妨害して、人々にネイティブアプリの作成を強制しようとしているのではないかと考えていますが、それは単なる憶測です。

全体として、これは開発者をかなり厄介な状況に置きます。優れたクロスプラットフォームソリューションはありません。 Appleに文句を言うことをお勧めします。それが私がやったことであり、iOSでIndexedDBベースのアプリを使用したいユーザーに同じことをするように依頼しました。まだAppleからの言葉はありません。

更新-WWDC2014で述べられているように、IndexeddbはiOS 8でサポートされるようになりました-しかし残念ながら かなりひどく壊れています

サブリソース整合性-

サブリソースの整合性により、ブラウザは、予期しない操作なしにファイルが配信されたことを確認できます。

既知の問題はありませんか?これまでのところ ?

私はあなたが一緒に行くことができることを提案します

モバイルが主なターゲットである場合のサブリソースベースのソリューション

indexeddbモバイルが主なターゲットではなく、モバイルで公開されている実装を使用している場合

上記のすべてがあなたにとって複雑すぎるように聞こえる場合は、

var localCache = {
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    //a cached version exists
    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); //log only!
        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);
    },
    timeout: 600, //in seconds
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        var complete = originalOptions.complete || $.noop,
            url = originalOptions.url;
        //remove jQuery cache as you have your 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 () {
    var url = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true,
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes, or cached version retrived
    function doSomething(data) {
        console.log(data);
    }

別の特定のJQUERYの答え?

それがあなたの質問に答えるかどうかはわかりませんが、それは役立つかもしれません。タイムアウト付きのajax呼び出しをキャッシュします。

プレフィルタリングで、キャッシュ用に追加するさまざまなPHP ajax呼び出しをリストします。この例では、キャッシュは10分のタイムアウトで有効になっています。

/*----------------------------*/
/* set ajax caching variables */
/*----------------------------*/
$.set_Ajax_Cache_filters = function () {
    var localCache = {
        timeout: 600000, // 10 minutes
        data: {}, //@type {{_: number, 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) {
            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);
        }
    };

    /*----------------------*/
    /* set ajax pre filters */
    /*----------------------*/
    $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
        // list of allowed url to cache
        if (url !== '..............file.php') {
            return false;
        }
        if (options.cache) {
            var complete = originalOptions.complete || $.noop,
                    url = originalOptions.url;

            options.cache = false;//remove jQuery cache using proprietary one
            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);
            };
        }
    });
};
2
cpugourou

これを行うには、ローカルキャッシュ、ajaxPrefilter、ajaxキャッシュオプションを使用するのが最善の方法です。これら3つの組み合わせにより、必要なソリッドキャッシュが作成され、簡単に制御できます。コード例を次に示します。

var localCache = {
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    //a cached version exists
    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); //log only!
        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);
    },
    timeout: 600, //in seconds
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        var complete = originalOptions.complete || $.noop,
            url = originalOptions.url;
        //remove jQuery cache as you have your 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 () {
    var url = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true,
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes, or cached version retrived
    function doSomething(data) {
        console.log(data);
    }

コーディングをお楽しみください

1
Omar El Don

これを試してみてください

    var cache = {};
var formatTweets(info) {  
    //formats tweets, does whatever you want with the Tweet information
};

//event
$('myForm').addEvent('submit',function() {
    var handle = $('handle').value; //davidwalshblog, for example
    var cacheHandle = handle.toLowerCase();
    if(cache[cacheHandle] != "undefined") {
        formatTweets(cache[cacheHandle]);
    }
    else {
        //gitter
        var myTwitterGitter = new TwitterGitter(handle,{
            count: 10,
            onComplete: function(tweets,user) {
                cache[cacheHandle] = tweets;
                formatTweets(tweets);
            }
        }).retrieve();
    }
});
0
Faisal