it-swarm.com.de

Welche Techniken sind möglich, um eine Ajax-Antwort in Javascript zwischenzuspeichern?

Ich implementiere einen Javascript-Modul-Manager, der Javascript-Dateien über das Objekt XHR lädt. Das Problem dieser Methode ist das Zwischenspeichern von Ressourcen:

  • Erstens stützen sich XHR auf den eingebauten Browser-Caching-Mechanismus, der in Ordnung ist, dessen Verhalten jedoch von der Browser-Implementierung abhängt.
  • Es gibt auch eine localStorage und eine basket.js , die localStorage verwendet, um heruntergeladene Skripte zwischenzuspeichern. Das Problem liegt in der begrenzten Speichergröße, die normalerweise 5-10 MB beträgt. Außerdem ist localStorage ein gemeinsamer Ort für viele Skripte, in denen auch Daten gespeichert werden.
  • Und es gibt eine Cache-Schnittstelle der ServiceWorker-API, die jedoch nur zur Laufzeit von ServiceWorker verfügbar ist, sodass sie zweifelsohne meinen Anforderungen entspricht.

Kennt jemand eine intelligente alte oder neue JavaScript-Caching-Technik, die er in seinem Projekt verwendet oder von der er vielleicht gehört hat?

Hinweis : Bitte schlagen Sie nicht vor, jQuery .ajax, eine Schnittstelle zu XHR, oder eine andere Bibliothek zu verwenden, die eine Schnittstelle zu eingebauten Javascript-Funktionen implementiert.

Bearbeiten : Es gab einige wertvolle Vorschläge:

  • Verwenden Sie die Bibliothek localForage. Die Bibliothek stellt eine einheitliche API für IndexedDB, WebSQL und localStorage dar, die je nach Browser verwendet wird.
  • Verwenden Sie IndexedDB, einen wirklich leistungsstarken Speicher ohne nennenswerte Speicherplatzbeschränkungen. Das einzige Problem ist, dass nur moderne Browser IndexedDB implementieren.
16
Eugene Tiurin

Dies ist spezifisch für JQUERY ....

Sie können Ajax als zwischengespeichert einrichten.

    $.ajaxSetup({ cache: true});

und wenn Sie für bestimmte Anrufe keine zwischengespeicherte Antwort erstellen möchten, rufen Sie an

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

Wenn Sie das Gegenteil wünschen (Cache für bestimmte Anrufe), können Sie am Anfang false und für bestimmte Anrufe true festlegen

Wenn Sie das Ergebnis einer Ajax-Antwort speichern möchten, können Sie den lokalen Speicher verwenden. Alle modernen Browser bieten Speicher-APIs. Sie können sie verwenden (localStorage oder sessionStorage), um Ihre Daten zu speichern.

Alles, was Sie tun müssen, ist, nachdem Sie die Antwort erhalten haben, diese im Browser-Speicher zu speichern. Wenn Sie dann das nächste Mal denselben Anruf finden, suchen Sie, ob die Antwort bereits gespeichert ist. Wenn ja, geben Sie die Antwort von dort zurück. Wenn nicht, tätigen Sie einen neuen Anruf.

Smartjax-Plugin macht auch ähnliche Dinge; Da Ihre Anforderung jedoch nur das Speichern der Anrufantwort ist, können Sie Ihren Code in Ihre jQuery-Ajax-Erfolgsfunktion schreiben, um die Antwort zu speichern. Und bevor Sie einen Anruf tätigen, überprüfen Sie einfach, ob die Antwort bereits gespeichert ist.

6
Somnath Muluk

Da indexeddb eine Methode zum Speichern von Daten auf Client-Seite ist, können Datenbankabfragen indiziert werden.

Und das sind die unterstützten Browser http://caniuse.com/#feat=indexeddb

Und das sind die einzigen Probleme

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.

Hier ist eine ähnliche Polyfüllung, die Sie ausprobieren können , aber meiner (wenn auch begrenzten) Erfahrung nach sind beide Polyfüllungen fehlerhaft/unvollständig. Beide haben auch viele offene Probleme bei GitHub, wenn Leute Probleme melden. Und als ich eine davon getestet habe (ich vergesse welche), war sie bedeutend langsamer als die native IndexedDB.

Möglicherweise ist es möglich, eine anständige Polyfüllung zu erstellen, aber die aktuellen scheinen den Job nicht zu erledigen.

Sollte ich WebSQL verwenden, das veraltet war?

Das Problem mit WebSQL ist, dass es in IE oder Firefox niemals unterstützt wird. Sie könnten wahrscheinlich mit WebSQL davonkommen, wenn Sie nur auf mobile Browser abzielen, zumindest bis Firefox OS oder Windows Phone einen signifikanten Marktanteil erreichen.

Gibt es Pläne, IndexedDB in Zukunft für alle nicht unterstützten Browser zu unterstützen?

Damit wir uns verstehen. Sie fragen nach Apple, da alle anderen Benutzer IndexedDB in ihrem neuesten Browser unterstützen (iOS Chrome verwendet die Rendering-Engine von Apple, da Apple keine weiteren Aktionen zulässt).

Apple unterstützt nicht nur IndexedDB nicht, sondern hat auch noch nichts öffentlich darüber gesagt (soweit ich das beurteilen kann ... und ich habe ziemlich viel gesucht). Welches scheint ziemlich seltsam. So wie ich es beurteilen kann, hat niemand eine Ahnung, ob Apple jemals vorhat, IndexedDB zu unterstützen. Der Verschwörungstheoretiker in mir denkt, dass sie vielleicht versuchen, HTML5-Apps zu sabotieren, um die Leute dazu zu zwingen, native Apps zu schreiben, aber das ist reine Spekulation.

Insgesamt sind wir Entwickler in einer ziemlich beschissenen Situation. Es gibt keine gute plattformübergreifende Lösung. Ich empfehle Ihnen, sich bei Apple darüber zu beschweren. Das habe ich getan und ich habe meine Benutzer, die meine auf IndexedDB basierende App auf iOS verwenden möchten, gebeten, dasselbe zu tun. Immer noch kein Wort von Apple.

UPDATE - Indexeddb wird jetzt in iOS 8 unterstützt, wie in WWDC 2014 angegeben - aber leider ist es ziemlich kaputt .

Berücksichtigen Sie auch, dass Subressource Integrität -

Mithilfe der Subressourcenintegrität können Browser überprüfen, ob die Datei ohne unerwartete Manipulation bereitgestellt wird.

Keine kenntnisse? bisher ?

Ich werde vorschlagen, dass Sie mitgehen können

Subresource basierte Lösung, wenn Mobile Ihr Hauptziel ist

indexeddb wenn mobile nicht Ihr Hauptziel ist und Sie die öffentlich verfügbaren Implementierungen für mobile verwenden

Wenn all das zu komplex für Sie klingt, dann

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);
    }

Noch eine spezifische JQUERY-Antwort?

Ich bin nicht sicher, ob es Ihre Frage beantwortet, aber das könnte helfen. Ajax-Aufrufe werden mit einer Zeitüberschreitung zwischengespeichert.

Listen Sie in der Vorfilterung die verschiedenen PHP Ajax-Aufrufe auf, die Sie zum Zwischenspeichern hinzufügen möchten. In diesem Beispiel wird der Cache mit einem Timeout von 10 Minuten aktiviert.

/*----------------------------*/
/* 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

Um dies zu tun, verwendet die beste Technik den lokalen Cache, ajaxPrefilter und die Option ajax cache. Durch die Kombination dieser drei Optionen erhalten Sie den gewünschten soliden Cache, den Sie einfach steuern können. Hier ein Codebeispiel:

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);
    }

Viel Spaß beim Programmieren

1
Omar El Don

Versuchen Sie, dies könnte funktionieren

    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