Zwischenspeichern einer JQuery-Ajax-Antwort in Javascript/Browser

Lesezeit: 10 Minuten

Ich möchte das Caching einer Ajax-Antwort in Javascript/Browser aktivieren.

Von dem jquery.ajax-Dokumente:

Standardmäßig werden Anfragen immer ausgegeben, aber der Browser kann Ergebnisse aus seinem Cache liefern. Um die Verwendung der zwischengespeicherten Ergebnisse zu verbieten, setzen Sie cache auf false. Damit die Anfrage einen Fehler meldet, wenn das Asset seit der letzten Anfrage nicht geändert wurde, setzen Sie ifModified auf true.

Keine dieser Adressen erzwingt jedoch das Caching.

Motivation:
Ich möchte setzen $.ajax({...}) Aufrufe in meinen Initialisierungsfunktionen, von denen einige dieselbe URL anfordern. Manchmal muss ich eine dieser Initialisierungsfunktionen aufrufen, manchmal mehrere.

Ich möchte also die Anfragen an den Server minimieren, wenn diese bestimmte URL bereits geladen wurde.

Ich könnte meine eigene Lösung entwickeln (mit einigen Schwierigkeiten!), aber ich würde gerne wissen, ob es dafür eine Standardmethode gibt.

  • Ich hätte es nicht für schwierig gehalten, zu verfolgen, welche URLs Sie bereits geladen haben, und die Ergebnisse gegen diese Liste zu speichern. Anschließend können Sie Ihre URLs überprüfen, bevor Sie einen AJAX-Aufruf tätigen. Voila – Sie haben Ihren eigenen Basis-Cache.

    Benutzer1864610

    14. Juni 13 um 08:33 Uhr

  • Sie könnten Ihrer Antwort auf dem Server den Header Cache-Control und Expires hinzufügen, sodass Ihr Server nur nach dem in diesen Werten konfigurierten Timeout aufgerufen werden sollte

    – hier und jetzt78

    14. Juni 13 um 08:37 Uhr

  • Es ist sehr lang, aber können Sie mir helfen zu verstehen, warum Sie Cache in Ajax-Anfragen benötigten (möglicherweise in Laiensprache)?

    – Asisch

    2. November 20 um 9:30 Uhr

Zwischenspeichern einer JQuery Ajax Antwort in JavascriptBrowser
TecHunter

cache:true funktioniert nur mit GET- und HEAD-Anfrage.

Sie könnten Ihre eigene Lösung rollen, wie Sie sagten, mit etwas in dieser Richtung:

var localCache = {
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    exist: function (url) {
        return localCache.data.hasOwnProperty(url) && localCache.data[url] !== null;
    },
    get: function (url) {
        console.log('Getting in cache for url' + url);
        return localCache.data[url];
    },
    set: function (url, cachedData, callback) {
        localCache.remove(url);
        localCache.data[url] = cachedData;
        if ($.isFunction(callback)) callback(cachedData);
    }
};

$(function () {
    var url="/echo/jsonp/";
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
            cache: true,
            beforeSend: function () {
                if (localCache.exist(url)) {
                    doSomething(localCache.get(url));
                    return false;
                }
                return true;
            },
            complete: function (jqXHR, textStatus) {
                localCache.set(url, jqXHR, doSomething);
            }
        });
    });
});

function doSomething(data) {
    console.log(data);
}

Arbeitsgeige hier

BEARBEITEN: Da dieser Beitrag immer beliebter wird, ist hier eine noch bessere Antwort für diejenigen, die den Timeout-Cache verwalten möchten und sich auch nicht mit dem ganzen Durcheinander in der beschäftigen müssen $.ajax() wie ich benutze $.ajaxPrefilter(). Jetzt nur noch einstellen {cache: true} reicht aus, um den Cache korrekt zu behandeln:

var localCache = {
    /**
     * timeout for cache in millis
     * @type {number}
     */
    timeout: 30000,
    /** 
     * @type {{_: number, data: {}}}
     **/
    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) {
        console.log('Getting in cache for url' + 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);
    }
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        var complete = originalOptions.complete || $.noop,
            url = originalOptions.url;
        //remove jQuery cache as we have our 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="/echo/jsonp/";
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
            cache: true,
            complete: doSomething
        });
    });
});

function doSomething(data) {
    console.log(data);
}

Und die Geige hier ACHTUNG, funktioniert nicht mit $.Deferred

Hier ist eine funktionierende, aber fehlerhafte Implementierung, die mit verzögert arbeitet:

var localCache = {
    /**
     * timeout for cache in millis
     * @type {number}
     */
    timeout: 30000,
    /** 
     * @type {{_: number, data: {}}}
     **/
    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) {
        console.log('Getting in cache for url' + 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);
    }
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        //Here is our identifier for the cache. Maybe have a better, safer ID (it depends on the object string representation here) ?
        // on $.ajax call we could also set an ID in originalOptions
        var id = originalOptions.url+ JSON.stringify(originalOptions.data);
        options.cache = false;
        options.beforeSend = function () {
            if (!localCache.exist(id)) {
                jqXHR.promise().done(function (data, textStatus) {
                    localCache.set(id, data);
                });
            }
            return true;
        };

    }
});

$.ajaxTransport("+*", function (options, originalOptions, jqXHR, headers, completeCallback) {

    //same here, careful because options.url has already been through jQuery processing
    var id = originalOptions.url+ JSON.stringify(originalOptions.data);

    options.cache = false;

    if (localCache.exist(id)) {
        return {
            send: function (headers, completeCallback) {
                completeCallback(200, "OK", localCache.get(id));
            },
            abort: function () {
                /* abort code, nothing needed here I guess... */
            }
        };
    }
});

$(function () {
    var url="/echo/jsonp/";
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
            cache: true
        }).done(function (data, status, jq) {
            console.debug({
                data: data,
                status: status,
                jqXHR: jq
            });
        });
    });
});

Geige HIER
Bei einigen Problemen ist unsere Cache-ID von der JSON-Objektdarstellung der json2-lib abhängig.

Verwenden Sie die Konsolenansicht (F12) oder FireBug, um einige vom Cache generierte Protokolle anzuzeigen.

  • Gibt es einen Grund, warum Sie einen Rückruf auf den setzen localCache.set Funktion? Warum nicht einfach doSomehing(jqXHR) nach dem Setzen des Caches?

    – kammil

    16. Juni 13 um 15:11 Uhr


  • Ich bevorzuge es einfach so, damit ich so etwas nicht tun muss doSomething(localCache.set(url,jqXHR)); aber es ist nur eine persönliche Vorliebe

    – TecHunter

    17. Juni 13 um 6:40 Uhr

  • Irgendwelche Vorschläge zur Verbesserung, um die Verwendung von $.ajax als Versprechen zu unterstützen? Das Zurückgeben von false von beforeSend bricht die Anfrage ab (wie es sollte), sodass vorhandene $.ajax(…).done(function(response) {…}).fail(…) jetzt nicht mehr funktionieren, da fail stattdessen aufgerufen wird als getan … und ich würde sie lieber nicht alle neu schreiben 🙁

    – Frank102

    6. Juni 14 um 17:42 Uhr


  • @TecHunter Vielen Dank dafür. Drei weitere geringfügige Verbesserungen könnten vorgenommen werden. Erstens, wenn mehrere Anforderungen gleichzeitig an dieselbe Ressource gestellt werden, verfehlen sie alle den Cache. Um dies zu beheben, möchten Sie möglicherweise den Cache für eine bestimmte “ID” bei der ersten Anfrage auf “Ausstehend” setzen und das Senden von Ergebnissen für nachfolgende Anfragen verschieben, bis die erste zurückkommt. Zweitens möchten Sie möglicherweise das Fehlerergebnis einer Anfrage zwischenspeichern, damit alle Anfragen für dieselbe Ressource dasselbe Ergebnis erhalten.

    – mjhm

    15. Oktober 14 um 14:08 Uhr

  • @TecHunter – Schöne Lösung, ich habe diese Lösung mit einer wichtigen Änderung verwendet. Wenn ein zwischengespeichertes Objekt in anderen Funktionen geändert wird, führt dies zu Problemen. Beim Festlegen und Abrufen eines zwischengespeicherten Objekts gebe ich eine Kopie dieses Objekts zurück, die wie unten gezeigt wird: localCache.data[url] = { _: new Date().getTime(), data: _.cloneDeep(cachedData, true) }; _.cloneDeep(localCache.data[url].data, true)

    – Bharat Patil

    31. März 16 um 4:42 Uhr

Zwischenspeichern einer JQuery Ajax Antwort in JavascriptBrowser
immajankmodi

Ich habe nach Caching für meinen Phonegap-App-Speicher gesucht und die Antwort von @TecHunter gefunden, die großartig, aber fertig ist localCache.

Ich habe festgestellt und erfahren, dass localStorage eine weitere Alternative ist, um die von einem Ajax-Aufruf zurückgegebenen Daten zwischenzuspeichern. Also habe ich eine Demo mit erstellt localStorage was anderen helfen wird, die es verwenden möchten localStorage anstatt localCache zum Caching.

Ajax-Aufruf:

$.ajax({
    type: "POST",
    dataType: 'json',
    contentType: "application/json; charset=utf-8",
    url: url,
    data: '{"Id":"' + Id + '"}',
    cache: true, //It must "true" if you want to cache else "false"
    //async: false,
    success: function (data) {
        var resData = JSON.parse(data);
        var Info = resData.Info;
        if (Info) {
            customerName = Info.FirstName;
        }
    },
    error: function (xhr, textStatus, error) {
        alert("Error Happened!");
    }
});

So speichern Sie Daten in localStorage:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
if (options.cache) {
    var success = originalOptions.success || $.noop,
        url = originalOptions.url;

    options.cache = false; //remove jQuery cache as we have our own localStorage
    options.beforeSend = function () {
        if (localStorage.getItem(url)) {
            success(localStorage.getItem(url));
            return false;
        }
        return true;
    };
    options.success = function (data, textStatus) {
        var responseData = JSON.stringify(data.responseJSON);
        localStorage.setItem(url, responseData);
        if ($.isFunction(success)) success(responseJSON); //call back to original ajax call
    };
}
});

Wenn Sie localStorage entfernen möchten, verwenden Sie die folgende Anweisung, wo immer Sie möchten:

localStorage.removeItem("Info");

Hoffe es hilft anderen!

  • Hallo, ein localStorage.removeItem("Info");über die "info" ist es die URL?

    – Vsogrimen

    25. Januar 16 um 2:39 Uhr


  • @vsogrimen info ist das Objekt zum Speichern der Daten in localStorage.

    – immajankmodi

    25. Januar 16 um 09:26 Uhr


  • erhalte weiterhin responseJSON is not defined. Gibt es eine Möglichkeit, dies zu beheben? (Mein Datentyp ist HTML)

    – Nikita 웃

    6. Februar 16 um 7:21 Uhr


  • @CreativeMind, entferne reponseJOSN und verwende „var responseData = JSON.stringify( data );“ Machen Sie stattdessen dasselbe mit Erfolg ( data )

    – Unico

    3. August 17 um 10:05 Uhr

  • Ich bevorzuge localStorage, da ich Cache für mehrere Anfragen benötigte.

    – KeitelDOG

    11. März 19 um 17:02 Uhr

Alle modernen Browser bieten Ihnen Speicher-APIs. Sie können sie (localStorage oder sessionStorage) verwenden, um Ihre Daten zu speichern.

Alles, was Sie tun müssen, ist, nachdem Sie die Antwort erhalten haben, sie im Browserspeicher 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, ruf nochmal an.

Smartjax Das 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 anrufen, prüfen Sie einfach, ob die Antwort bereits gespeichert ist.

  • Ich habe Antworten in IndexedDB gespeichert, gibt es eine Möglichkeit, IndexedDB zu überprüfen? Wenn ich Sitzungsspeicher verwende, gibt es außerdem eine Möglichkeit, mit jQuery zu überprüfen, ob eine Antwort vorhanden ist oder nicht. Ich kann keine andere Bibliothek als jQuery einbinden. Danke,

    – Abhishek Aggarwal

    28. März 19 um 8:19 Uhr


1643466309 443 Zwischenspeichern einer JQuery Ajax Antwort in JavascriptBrowser
Frühling

Wenn ich deine Frage verstanden habe, hier die Lösung:

    $.ajaxSetup({ cache: true});

und für bestimmte Anrufe

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

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

Alte Frage, aber meine Lösung ist etwas anders.

Ich habe eine Single-Page-Web-App geschrieben, die ständig vom Benutzer ausgelöste Ajax-Aufrufe durchführte, und um es noch schwieriger zu machen, waren Bibliotheken erforderlich, die andere Methoden als jquery verwendeten (wie Dojo, natives xhr usw.). Ich habe ein Plugin für eines geschrieben meine eigenen Bibliotheken Ajax-Anfragen so effizient wie möglich zwischenzuspeichern, sodass sie in allen gängigen Browsern funktionieren, unabhängig davon, welche Bibliotheken für den Ajax-Aufruf verwendet wurden.

Die Lösung verwendet jSQL (von mir geschrieben – eine in Javascript geschriebene clientseitige persistente SQL-Implementierung, die indexeddb und andere dom-Speichermethoden verwendet) und mit einer anderen Bibliothek namens gebündelt ist XHRCreep (geschrieben von mir), das eine komplette Neufassung des nativen XHR-Objekts ist.

Um alles zu implementieren, was Sie tun müssen, ist das Plugin in Ihre Seite einzubinden, was hier ist.

Es gibt zwei Möglichkeiten:

jSQL.xhrCache.max_time = 60;

Legen Sie das Höchstalter in Minuten fest. Alle zwischengespeicherten Antworten, die älter sind, werden erneut angefordert. Standard ist 1 Stunde.

jSQL.xhrCache.logging = true;

Wenn dies auf „true“ gesetzt ist, werden Schein-XHR-Aufrufe zum Debuggen in der Konsole angezeigt.

Sie können den Cache auf jeder beliebigen Seite über löschen

jSQL.tables = {}; jSQL.persist();

  • Ich kann Ihr Plugin in GitHub und auf der offiziellen Website nicht finden. Bitte aktualisieren Sie Ihre Antwort. Ich brauche Ihr Plugin 🙂 Ich bin ein Follower von Ihnen in GitHub. Gute Arbeit 😉 @occams-razor

    – Alican Kablan

    21. Dezember 18 um 12:21 Uhr


1643466310 598 Zwischenspeichern einer JQuery Ajax Antwort in JavascriptBrowser
Benutzer1634982

        function getDatas() {
            let cacheKey = 'memories';

            if (cacheKey in localStorage) {
                let datas = JSON.parse(localStorage.getItem(cacheKey));

                // if expired
                if (datas['expires'] < Date.now()) {
                    localStorage.removeItem(cacheKey);

                    getDatas()
                } else {
                    setDatas(datas);
                }
            } else {
                $.ajax({
                    "dataType": "json",
                    "success": function(datas, textStatus, jqXHR) {
                        let today = new Date();

                        datas['expires'] = today.setDate(today.getDate() + 7) // expires in next 7 days

                        setDatas(datas);

                        localStorage.setItem(cacheKey, JSON.stringify(datas));
                    },
                    "url": "http://localhost/phunsanit/snippets/PHP/json.json_encode.php",
                });
            }
        }

        function setDatas(datas) {
            // display json as text
            $('#datasA').text(JSON.stringify(datas));

            // your code here
           ....

        }

        // call
        getDatas();

Geben Sie hier die Linkbeschreibung ein

  • Ich kann Ihr Plugin in GitHub und auf der offiziellen Website nicht finden. Bitte aktualisieren Sie Ihre Antwort. Ich brauche Ihr Plugin 🙂 Ich bin ein Follower von Ihnen in GitHub. Gute Arbeit 😉 @occams-razor

    – Alican Kablan

    21. Dezember 18 um 12:21 Uhr


.

688830cookie-checkZwischenspeichern einer JQuery-Ajax-Antwort in Javascript/Browser

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy