Wann verfallen Elemente im lokalen HTML5-Speicher?


336

Wie lange sind Daten in localStorage (als Teil des DOM-Speichers in HTML5) verfügbar? Kann ich eine Ablaufzeit für die Daten festlegen, die ich in localStorage eingefügt habe?


3
Verwenden Sie localStorage nicht, wenn möglich, da es nie automatisch abläuft. Dort können Sie sessionStorage verwenden. Es ist vorzuziehen
Dharmendrasinh Chudasama

Antworten:


215

Es ist nicht möglich, den Ablauf anzugeben. Es liegt ganz beim Benutzer.

https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

Natürlich ist es möglich, dass etwas, das Ihre Anwendung auf dem Client speichert, später nicht mehr vorhanden ist. Der Benutzer kann den lokalen Speicher explizit entfernen, oder der Browser kann auf Speicherplatzprobleme stoßen. Es ist gut, defensiv zu programmieren. Im Allgemeinen bleiben die Dinge jedoch "für immer", basierend auf einer praktischen Definition dieses Wortes.

Bearbeiten - Natürlich kann Ihre eigene Anwendung Inhalte aktiv entfernen, wenn sie zu alt ist. Das heißt, Sie können explizit eine Art Zeitstempel in das, was Sie gespeichert haben, einfügen und diesen später verwenden, um zu entscheiden, ob Informationen gelöscht werden sollen oder nicht.


1
Kann der Benutzer also darauf zählen, dass die Daten beispielsweise nach einem Jahr verfügbar sind? Kann der Entwickler darauf zählen, dass die Daten verfügbar sind, wenn der Benutzer sie nicht ausdrücklich löscht?
Andres Riofrio

6
@AndresRiofrio Ich kann keine Dokumentation von Mozilla, Microsoft oder dem W3C finden, die einen obligatorischen Ablauf vorsieht. Daher denke ich, dass die Antwort lautet: Ja, der Benutzeragent soll gespeicherte Inhalte für immer aufbewahren oder bis der Benutzer ausdrücklich das Löschen anfordert (oder ich denke, bis Ihre eigene Anwendung ihre eigenen Inhalte löscht).
Pointy

3
Dies bedeutet auch, dass Ihr Browser weiter wächst. Sie verwenden eine App einmal, sie speichert ihre Inhalte in Ihrem Browser und bleibt dort für immer ...
Pieter van Kampen

1
Die Menge an localStorage-Daten, die Sie pro Website speichern können, liegt bei etwa 10 MB, aber eine durchschnittliche Website speichert nicht viel mehr als ein paar Zeichenfolgen, sodass mir Speicherplatz nichts ausmacht
Juan

1
Firefox hat hier eine dokumentierte Räumungsrichtlinie .
ShreevatsaR

268

Ich würde vorschlagen, den Zeitstempel in dem Objekt zu speichern, das Sie im localStorage speichern

var object = {value: "value", timestamp: new Date().getTime()}
localStorage.setItem("key", JSON.stringify(object));

Sie können das Objekt analysieren, den Zeitstempel abrufen und mit dem aktuellen Datum vergleichen und bei Bedarf den Wert des Objekts aktualisieren.

var object = JSON.parse(localStorage.getItem("key")),
    dateString = object.timestamp,
    now = new Date().getTime().toString();

compareTime(dateString, now); //to implement

3
Auch wenn die Clientzeit nicht konsistent ist, können Sie stattdessen eine Möglichkeit finden, Ihre Serverzeit zu verwenden. Als würde man den Zeitstempel in ein Div wiederholen.
Supreme Dolphin

Würden Sie den Zeitstempel in einem Zeitintervall (z. B. settimoutalle 5 Sekunden) oder für jede Anforderung, die der Client an den Server sendet, analysieren und vergleichen ?
Ibubi

Der bessere Weg ist, Daten für jede Benutzeranfrage zu vergleichen
Terai

36

Sie können lscache verwenden . Dies wird automatisch für Sie erledigt, einschließlich der Fälle, in denen die Speichergröße den Grenzwert überschreitet. In diesem Fall werden Elemente beschnitten, die dem angegebenen Ablauf am nächsten kommen.

Aus dem readme:

lscache.set

Stores the value in localStorage. Expires after specified number of minutes.

Arguments
key (string)
value (Object|string)
time (number: optional)

Dies ist der einzige wirkliche Unterschied zwischen den regulären Speichermethoden. Holen, entfernen, usw. funktionieren gleich.

Wenn Sie nicht so viele Funktionen benötigen, können Sie einfach einen Zeitstempel mit dem Wert (über JSON) speichern und auf Ablauf prüfen.

Bemerkenswerterweise gibt es einen guten Grund, warum der lokale Speicher dem Benutzer überlassen bleibt. Dinge wie lscache sind jedoch nützlich, wenn Sie extrem temporäre Daten speichern müssen.


Vielen Dank! Das ist großartig für das, was ich brauche - die Daten müssen nur da sein, falls der Benutzer einen Booboo macht oder der Browser geschlossen wird, bevor er seine Arbeit gespeichert hat, aber es gibt zu viele Daten für Cookies. Ich benutze es in Verbindung mit pieroxy.net/blog/pages/lz-string/index.html .
Peter Smartt

34

Brynner Ferreira hat einen guten Punkt gebracht: Speichern eines Geschwisterschlüssels, in dem sich die Ablaufinformationen befinden. Auf diese Weise müssen Sie , wenn Sie über eine große Anzahl von Schlüsseln verfügen oder wenn Ihre Werte große Json-Objekte sind , diese nicht analysieren, um auf den Zeitstempel zuzugreifen.

Hier folgt eine verbesserte Version:

 /*  removeStorage: removes a key from localStorage and its sibling expiracy key
    params:
        key <string>     : localStorage key to remove
    returns:
        <boolean> : telling if operation succeeded
 */
 function removeStorage(name) {
    try {
        localStorage.removeItem(name);
        localStorage.removeItem(name + '_expiresIn');
    } catch(e) {
        console.log('removeStorage: Error removing key ['+ key + '] from localStorage: ' + JSON.stringify(e) );
        return false;
    }
    return true;
}
/*  getStorage: retrieves a key from localStorage previously set with setStorage().
    params:
        key <string> : localStorage key
    returns:
        <string> : value of localStorage key
        null : in case of expired key or failure
 */
function getStorage(key) {

    var now = Date.now();  //epoch time, lets deal only with integer
    // set expiration for storage
    var expiresIn = localStorage.getItem(key+'_expiresIn');
    if (expiresIn===undefined || expiresIn===null) { expiresIn = 0; }

    if (expiresIn < now) {// Expired
        removeStorage(key);
        return null;
    } else {
        try {
            var value = localStorage.getItem(key);
            return value;
        } catch(e) {
            console.log('getStorage: Error reading key ['+ key + '] from localStorage: ' + JSON.stringify(e) );
            return null;
        }
    }
}
/*  setStorage: writes a key into localStorage setting a expire time
    params:
        key <string>     : localStorage key
        value <string>   : localStorage value
        expires <number> : number of seconds from now to expire the key
    returns:
        <boolean> : telling if operation succeeded
 */
function setStorage(key, value, expires) {

    if (expires===undefined || expires===null) {
        expires = (24*60*60);  // default: seconds for 1 day
    } else {
        expires = Math.abs(expires); //make sure it's positive
    }

    var now = Date.now();  //millisecs since epoch time, lets deal only with integer
    var schedule = now + expires*1000; 
    try {
        localStorage.setItem(key, value);
        localStorage.setItem(key + '_expiresIn', schedule);
    } catch(e) {
        console.log('setStorage: Error setting key ['+ key + '] in localStorage: ' + JSON.stringify(e) );
        return false;
    }
    return true;
}

Sollte die elseZeile in setStorage () nicht sein expires = Math.abs(1000*expires); //make sure it's positive?
Alissonmüller

Nur ein Punkt für den getStorageAnruf. Wenn Sie versuchen, _expiresIndirekt auf die Version des Schlüssels zuzugreifen , wird der Schlüssel zu ..._expiresIn_expiresIndem, der natürlich nicht vorhanden ist, sodass der ursprüngliche ..._expiresInSchlüssel entfernt wird. Wenn Sie das nächste Mal auf den ursprünglichen Schlüssel zugreifen, ist der Schlüssel ..._expiresInnicht vorhanden und löscht das Original Schlüssel. Ich würde vorschlagen, dafür zu fangen, da ich in einem meiner Projekte darauf gestoßen bin. if(key.indexOf('_expiresIn') > -1) { return localStorage.getItem(key); }
Akousmata

24

Während der lokale Speicher keinen Ablaufmechanismus bietet, tun dies Cookies. Durch einfaches Koppeln eines lokalen Speicherschlüssels mit einem Cookie können Sie auf einfache Weise sicherstellen, dass der lokale Speicher mit denselben Ablaufparametern wie ein Cookie aktualisiert werden kann.

Beispiel in jQuery:

if (!$.cookie('your_key') || !localStorage.getItem('your_key')) {
    //get your_data from server, then...
    localStorage.setItem('your_key', 'your_data' );
    $.cookie('your_key', 1);
} else {
    var your_data = localStorage.getItem('your_key');
}
// do stuff with your_data

In diesem Beispiel wird ein Cookie mit dem Standardparameter festgelegt, der beim Schließen des Browsers abläuft. Wenn der Browser geschlossen und erneut geöffnet wird, wird der lokale Datenspeicher für Ihre_Daten durch einen serverseitigen Aufruf aktualisiert.

Beachten Sie, dass dies nicht genau mit dem Entfernen des lokalen Datenspeichers identisch ist. Stattdessen wird der lokale Datenspeicher aktualisiert, sobald das Cookie abläuft. Wenn Ihr Hauptziel jedoch darin besteht, mehr als 4 KB clientseitig speichern zu können (die Beschränkung für die Cookie-Größe), können Sie mit dieser Kombination aus Cookie und lokalem Speicher eine größere Speichergröße mit denselben Ablaufparametern wie ein Cookie erzielen .


Cookies können gelöscht und, noch schlimmer, vollständig deaktiviert werden.
Supreme Dolphin

1
Diese Lösung gefällt mir am besten, da der Browser damit den Ablauf unserer Speicherlösung bewältigen kann, ohne andere Bibliotheken verwenden oder lokale Speicherdaten manuell verwalten zu müssen.
ecc

10
Beachten Sie, dass Cookies in JEDER Anfrage gesendet werden.
Lucas Freitas

24

Hier wird dringend empfohlen, sessionStorage zu verwenden

  • Es ist dasselbe wie localStorage, wird jedoch zerstört, wenn die Sitzung zerstört / der Browser geschlossen wird
  • Auch localStorage kann zwischen Registerkarten geteilt werden, während sessionStorage nur auf der aktuellen Registerkarte verwendet werden kann. Der Wert ändert sich jedoch nicht auf der Aktualisierungsseite oder auf der Seite
  • sessionStorage ist auch nützlich, um den Netzwerkverkehr gegen Cookies zu reduzieren

für Sollwert verwenden

sessionStorage.setItem("key","my value");

für Get Value Use

var value = sessionStorage.getItem("key");

Klicken Sie hier, um die API anzuzeigen

Alle Möglichkeiten zum Setzen sind

  sessionStorage.key = "my val";
  sessionStorage["key"] = "my val";
  sessionStorage.setItem("key","my value");

Alle Wege zu bekommen sind

  var value = sessionStorage.key;
  var value = sessionStorage["key"];
  var value = sessionStorage.getItem("key");

8
Beachten Sie, dass sessionStoragenicht funktioniert, um Daten zwischen Registerkarten zu teilen
Bhargava Mummadireddy

14

Der Lebenszyklus wird von der Anwendung / dem Benutzer gesteuert.

Aus dem Standard :

Benutzeragenten sollten Daten aus den lokalen Speicherbereichen nur aus Sicherheitsgründen oder auf Aufforderung des Benutzers ablaufen lassen. Benutzerprogramme sollten immer vermeiden, Daten zu löschen, während ein Skript ausgeführt wird, das auf diese Daten zugreifen kann.


10

Aus dem W3C-Entwurf:

Benutzeragenten sollten Daten aus den lokalen Speicherbereichen nur aus Sicherheitsgründen oder auf Aufforderung des Benutzers ablaufen lassen. Benutzerprogramme sollten immer vermeiden, Daten zu löschen, während ein Skript ausgeführt wird, das auf diese Daten zugreifen kann.

Sie möchten Ihre Aktualisierungen in Ihrem Zeitplan mit setItem (Schlüssel, Wert) durchführen. Dadurch wird der angegebene Schlüssel entweder hinzugefügt oder mit den neuen Daten aktualisiert.


Hmm ... vielleicht wäre es eine gute Idee, ein Datum als Teil der Daten aufzulisten? Oder verwenden Sie jedes Mal einen anderen Schlüssel, wenn sich die Daten ändern.
DisgruntledGoat

9
// Functions
function removeHtmlStorage(name) {
    localStorage.removeItem(name);
    localStorage.removeItem(name+'_time');
}

function setHtmlStorage(name, value, expires) {

    if (expires==undefined || expires=='null') { var expires = 3600; } // default: 1h

    var date = new Date();
    var schedule = Math.round((date.setSeconds(date.getSeconds()+expires))/1000);

    localStorage.setItem(name, value);
    localStorage.setItem(name+'_time', schedule);
}

function statusHtmlStorage(name) {

    var date = new Date();
    var current = Math.round(+date/1000);

    // Get Schedule
    var stored_time = localStorage.getItem(name+'_time');
    if (stored_time==undefined || stored_time=='null') { var stored_time = 0; }

    // Expired
    if (stored_time < current) {

        // Remove
        removeHtmlStorage(name);

        return 0;

    } else {

        return 1;
    }
}

// Status
var cache_status = statusHtmlStorage('cache_name');

// Has Data
if (cache_status == 1) {

    // Get Cache
    var data = localStorage.getItem('cache_name');
    alert(data);

// Expired or Empty Cache
} else {

    // Get Data
    var data = 'Pay in cash :)';
    alert(data);

    // Set Cache (30 seconds)
    if (cache) { setHtmlStorage('cache_name', data, 30); }

}

4
Ich mag diesen Ansatz, da nicht zuerst die Daten analysiert werden müssen.
Christophe

3

Wenn jemand das jStorage-Plugin von jQuery verwendet, kann es mit der Funktion setTTL zum Ablauf des jStorage-Plugins hinzugefügt werden

$.jStorage.set('myLocalVar', "some value");
$.jStorage.setTTL("myLocalVar", 24*60*60*1000); // 24 Hr.

3

Wenn jemand immer noch nach einer schnellen Lösung sucht und keine Abhängigkeiten wie jquery usw. möchte, habe ich eine Mini-Bibliothek geschrieben, die dem lokalen / Sitzungs- / benutzerdefinierten Speicher einen Ablauf hinzufügt. Sie finden sie hier mit Quelle:

https://github.com/RonenNess/ExpiredStorage


3

Sie können diesen versuchen.

var hours = 24; // Reset when storage is more than 24hours
var now = new Date().getTime();
var setupTime = localStorage.getItem('setupTime');
if (setupTime == null) {
     localStorage.setItem('setupTime', now)
} else {
    if(now-setupTime > hours*60*60*1000) {
         localStorage.clear()
         localStorage.setItem('setupTime', now);
    }
}

1

Problemumgehung mit eckigem und lokalem Futter:

angular.module('app').service('cacheService', function() {

  return {
    set: function(key, value, expireTimeInSeconds) {
      return localforage.setItem(key, {
        data: value,
        timestamp: new Date().getTime(),
        expireTimeInMilliseconds: expireTimeInSeconds * 1000
      })
    },
    get: function(key) {
      return localforage.getItem(key).then(function(item) {
        if(!item || new Date().getTime() > (item.timestamp + item.expireTimeInMilliseconds)) {
          return null
        } else {
          return item.data
        }
      })
    }
  }

})

Ich habe die Site überprüft und sehe keinen "expireTimeInMilliseconds" -Schlüssel in ihrer API. Ist es eine nicht dokumentierte / nicht unterstützte Einstellung?
aaaaaa

1
@PhilOlson, das ist eine benutzerdefinierte Implementierung, die ich verwendet habe localforage. expireTimeInMillisecondsist kein localforageAttribut, sondern eine Variable, mit der ich überprüft habe, ob die gespeicherten Daten abgelaufen sein müssen. Überprüfen Sie die getFunktionsdefinition in meinem Beispiel.
Tomas Romero

Wow localforageist nicht die leichte kleine
Helferklasse, die

1

@ sebarmelis Ansatz ist meiner Meinung nach der beste, aber wenn Sie nur möchten, dass Daten für die Dauer einer Sitzung erhalten bleiben, sessionStorageist dies wahrscheinlich eine bessere Option:

Dies ist ein globales Objekt (sessionStorage), das einen Speicherbereich verwaltet, der für die Dauer der Seitensitzung verfügbar ist. Eine Seitensitzung dauert so lange, wie der Browser geöffnet ist und über das Neuladen und Wiederherstellen von Seiten hinaus Bestand hat. Wenn Sie eine Seite in einem neuen Tab oder Fenster öffnen, wird eine neue Sitzung initiiert.

MDN: sessionStorage


1

Zum Nutzen der Suchenden:

Wie Fernando wollte ich keine Ladung json hinzufügen, wenn die gespeicherten Werte einfach waren. Ich musste nur einige Interaktionen mit der Benutzeroberfläche verfolgen und die Daten relevant halten (z. B. wie ein Benutzer eine E-Commerce-Website vor dem Auschecken verwendet hat).

Dies erfüllt nicht alle Kriterien, ist aber hoffentlich ein schneller Starter zum Kopieren und Einfügen für jemanden und spart das Hinzufügen einer weiteren Bibliothek.

HINWEIS: Dies ist nicht sinnvoll, wenn Sie die Elemente einzeln abrufen müssen.

// Addition
if(window.localStorage){
    localStorage.setItem('myapp-' + new Date().getTime(), 'my value');
}

// Removal of all expired items
if(window.localStorage){

    // two mins - (1000 * 60 * 20) would be 20 mins
    var expiryTime = new Date().getTime() - (1000 * 60 * 2);

    var deleteRows = [];
    for(var i=0; i < localStorage.length; i++){
        var key = localStorage.key(i);
        var partsArray = key.split('-');
        // The last value will be a timestamp
        var lastRow = partsArray[partsArray.length - 1];

        if(lastRow && parseInt(lastRow) < expiryTime){
            deleteRows.push(key);
        }
    }
    // delete old data
    for(var j=0; j < deleteRows.length; j++){
        localStorage.removeItem(deleteRows[j]);
    }
}

0

Wenn Sie mit dem locaStorage-Objekt des Browsers vertraut sind , wissen Sie, dass keine Angabe einer Ablaufzeit vorgesehen ist . Wir können jedoch Javascript verwenden, um eine TTL (Time to Live) hinzuzufügen, um Elemente in locaStorage nach Ablauf einer bestimmten Zeitspanne ungültig zu machen.

function setLocalStorage(key, value, ttl) {
    // `item` is an object which contains the original value
    // as well as the time when it's supposed to expire
    const item = {
        value: value,
        expiry: ttl <= 0 ? -1 : new Date().getTime() + ttl
    };
    localStorage.setItem(key, JSON.stringify(item));
}

function getLocalStorage(key) {
    const itemStr = localStorage.getItem(key);
    // if the item doesn't exist, return null
    if (!itemStr) {
        return null;
    }
    const item = JSON.parse(itemStr);
    // compare the expiry time of the item with the current time
    if (item.expiry > 0 && new Date().getTime() > item.expiry) {
        // If the item is expired, delete the item from storage
        // and return null
        localStorage.removeItem(key);
        return null;
    }
    return item.value;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.