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?

user280427
quelle
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.

Spitze
quelle
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
sebarmeli
quelle
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.

huyz
quelle
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;
}
Fernando Fabreti
quelle
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 .

Robert Peake
quelle
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");
Dharmendrasinh Chudasama
quelle
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.

jldupont
quelle
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.

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

}
Brynner Ferreira
quelle
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.
Amit
quelle
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

Ronen Ness
quelle
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);
    }
}
Jay Chauhan
quelle
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
        }
      })
    }
  }

})
Tomas Romero
quelle
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

Kevin Leary
quelle
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]);
    }
}
HockeyJ
quelle
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;
}
iProDev
quelle