Quando scadono gli oggetti nella memoria locale HTML5?


337

Per quanto tempo sono disponibili i dati memorizzati in localStorage (come parte di DOM Storage in HTML5)? Posso impostare un tempo di scadenza per i dati che inserisco in localStorage?


3
non usare localStorage se possibile perché non scade mai automaticamente, lì puoi usare sessionStorage è più preferibile
Dharmendrasinh Chudasama

Risposte:


215

Non è possibile specificare la scadenza. Dipende completamente dall'utente.

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

Ovviamente, è possibile che qualcosa che l'applicazione memorizza sul client potrebbe non essere presente in seguito. L'utente può eliminare esplicitamente l'archiviazione locale o il browser può eseguire considerazioni sullo spazio. È bene programmare in modo difensivo. In genere, tuttavia, le cose rimangono "per sempre" sulla base di una definizione pratica di quella parola.

modifica - ovviamente, la tua applicazione può rimuovere attivamente roba se decide che è troppo vecchia. Cioè, puoi includere esplicitamente una sorta di data / ora in ciò che hai salvato e quindi usarlo in seguito per decidere se le informazioni devono essere scaricate o meno.


1
Quindi l'utente può contare sui dati disponibili dopo, diciamo, un anno? Lo sviluppatore può contare sui dati disponibili a meno che l'utente non li elimini esplicitamente ?
Andres Riofrio,

6
@AndresRiofrio Non riesco a trovare alcuna documentazione di Mozilla o Microsoft o del W3C che preveda una scadenza obbligatoria. Quindi penso che la risposta sia che si, l'agente utente dovrebbe mantenere le cose archiviate per sempre, o fino a quando l'utente non chiede esplicitamente che vengano eliminate (o suppongo che la tua stessa applicazione non elimini le sue cose).
Punta a punta il

3
Questo significa anche che il tuo browser continua a crescere. Una volta usi un'app, memorizza le cose nel tuo browser e rimane lì per sempre ....
Pieter van Kampen,

1
La quantità di dati di archivio locale che è possibile archiviare per sito Web è di circa 10 MB, ma un sito medio non memorizza molto più di poche stringhe, quindi non mi dispiacerebbe lo spazio di archiviazione
Juan,

1
Firefox ha una politica di sfratto documentata qui .
ShreevatsaR,

269

Suggerirei di memorizzare il timestamp nell'oggetto che memorizzi nel localStorage

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

È possibile analizzare l'oggetto, ottenere il timestamp e confrontarlo con la data corrente e, se necessario, aggiornare il valore dell'oggetto.

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

compareTime(dateString, now); //to implement

3
Bene, anche se l'ora del client non è coerente, puoi comunque trovare un modo di utilizzare l'ora del tuo server. Come riecheggiare il timestamp in un div.
Supreme Dolphin,

Vuoi analizzare e confrontare il timestamp in un intervallo di tempo (ad esempio settimoutper ogni 5 secondi) o per ogni richiesta che il client invia al server?
ibubi,

il modo migliore è confrontare le date per ogni richiesta dell'utente
Terai,

36

Puoi usare lscache . Gestisce questo per te automaticamente, compresi i casi in cui la dimensione della memoria supera il limite. In tal caso, inizia a eliminare gli oggetti più vicini alla scadenza specificata.

Dal readme:

lscache.set

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

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

Questa è l'unica vera differenza tra i normali metodi di archiviazione. Ottieni, rimuovi, ecc. Funziona allo stesso modo.

Se non hai bisogno di molte funzionalità, puoi semplicemente memorizzare un timestamp con il valore (tramite JSON) e verificarne la scadenza.

Degno di nota, c'è una buona ragione per cui l'archiviazione locale è lasciata all'utente. Ma cose come lscache sono utili quando è necessario archiviare dati estremamente temporanei.


Grazie! Questo è fantastico per quello di cui ho bisogno: i dati devono essere lì nel caso in cui l'utente faccia un booboo o il browser si chiuda prima di aver salvato il proprio lavoro, ma ci sono troppi dati per i cookie. Lo sto usando insieme a pieroxy.net/blog/pages/lz-string/index.html .
Peter Smartt,

34

Brynner Ferreira, ha portato un buon punto: memorizzare una chiave di pari livello dove risiedono le informazioni di scadenza. In questo modo, se si dispone di una grande quantità di chiavi o se i valori sono oggetti Json di grandi dimensioni , non è necessario analizzarli per accedere al timestamp.

qui segue una versione migliorata:

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

In setStorage (), la elselinea non dovrebbe essere expires = Math.abs(1000*expires); //make sure it's positive?
alissonmuller,

Solo un punto per la getStoragechiamata. Se provi ad accedere direttamente alla _expiresInversione della chiave, la chiave diventa quella ..._expiresIn_expiresInche ovviamente non esiste, quindi rimuove la ..._expiresInchiave originale , quindi la prossima volta che accedi alla chiave originale, la ..._expiresInnon esiste e cancella l'originale chiave. Suggerirei di intrappolarlo mentre mi imbattevo in uno dei miei progetti. if(key.indexOf('_expiresIn') > -1) { return localStorage.getItem(key); }
Akousmata,

24

Mentre l'archiviazione locale non fornisce un meccanismo di scadenza, i cookie lo fanno. Il semplice accoppiamento di una chiave di archiviazione locale con un cookie fornisce un modo semplice per garantire che l'archiviazione locale possa essere aggiornata con gli stessi parametri di scadenza di un cookie.

Esempio 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 questo esempio un cookie con il parametro predefinito scade alla chiusura del browser. Pertanto, quando il browser viene chiuso e riaperto, l'archivio dati locale per your_data viene aggiornato da una chiamata sul lato server.

Si noti che ciò non è esattamente uguale alla rimozione dell'archivio dati locale, ma aggiorna l'archivio dati locale ogni volta che scade il cookie. Tuttavia, se il tuo obiettivo principale è quello di essere in grado di archiviare più di 4K lato client (la limitazione per le dimensioni dei cookie), questa associazione di cookie e archiviazione locale ti aiuterà a raggiungere dimensioni di archiviazione maggiori utilizzando gli stessi parametri di scadenza di un cookie .


I cookie possono essere cancellati e, peggio ancora, possono essere completamente disattivati.
Supreme Dolphin,

1
Questa soluzione mi piace al meglio perché consente al browser di gestire la scadenza della nostra soluzione di archiviazione senza dover utilizzare altre librerie o gestire manualmente le date di archiviazione locali.
ecc.

10
Tieni presente che i cookie vengono inviati in OGNI richiesta.
Lucas Freitas,

24

Qui si consiglia vivamente di utilizzare sessionStorage

  • è uguale a localStorage ma viene distrutto quando la sessione viene distrutta / la chiusura del browser
  • anche localStorage può condividere tra le schede mentre sessionStorage può utilizzare solo nella scheda corrente, ma il valore non cambia nella pagina di aggiornamento o cambia la pagina
  • sessionStorage è anche utile per ridurre il traffico di rete contro i cookie

per l'uso del valore impostato

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

per ottenere valore

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

clicca qui per visualizzare api

tutti i modi per impostare sono

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

tutti i modi per ottenere sono

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

8
Nota che sessionStoragenon funziona per condividere i dati tra le schede
Bhargava Mummadireddy,

14

Il ciclo di vita è controllato dall'applicazione / utente.

Dallo standard :

I programmi utente devono far scadere i dati dalle aree di archiviazione locali solo per motivi di sicurezza o quando richiesto dall'utente. Gli interpreti dovrebbero sempre evitare di eliminare i dati mentre è in esecuzione uno script che potrebbe accedere a tali dati.


10

Dalla bozza del W3C:

I programmi utente devono far scadere i dati dalle aree di archiviazione locali solo per motivi di sicurezza o quando richiesto dall'utente. Gli interpreti dovrebbero sempre evitare di eliminare i dati mentre è in esecuzione uno script che potrebbe accedere a tali dati.

Ti consigliamo di fare gli aggiornamenti sul tuo programma usando setItem (chiave, valore); che aggiungerà o aggiornerà la chiave fornita con i nuovi dati.


Hmm ... forse elencare una data come parte dei dati sarebbe una buona idea? O forse usando una chiave diversa ogni volta che i dati cambiano.
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
Mi piace questo approccio, in quanto non richiede prima di analizzare i dati.
Christophe,

3

Se qualcuno utilizza jStorage Plugin di jQuery, può essere aggiunto scadenza con la funzione setTTL se plugin jStorage

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

3

Se qualcuno sta ancora cercando una soluzione rapida e non desidera dipendenze come jquery ecc. Ho scritto una mini lib che aggiunge la scadenza all'archiviazione locale / sessione / personalizzata, puoi trovarla qui con l'origine:

https://github.com/RonenNess/ExpiredStorage


3

Puoi provare questo.

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

Soluzione alternativa utilizzando angular e localforage:

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

})

Ho controllato il sito e non vedo alcuna chiave "expireTimeInMilliseconds" nella loro API. È un'impostazione non documentata / non supportata?
aaaaaa,

1
@PhilOlson è un'implementazione personalizzata che ho usato usando localforage. expireTimeInMillisecondsnon è un localforageattributo, ma una variabile che ho usato per verificare se i dati memorizzati devono essere scaduti. Controlla la getdefinizione della funzione sul mio esempio.
Tomas Romero,

wow localforagenon è il piccolo aiutante leggero che mi aspettavo
Simon_Weaver,

1

Secondo me, l'approccio di @ sebarmeli è il migliore, ma se vuoi che i dati persistano per la durata di una sessione, sessionStorageprobabilmente è un'opzione migliore:

Questo è un oggetto globale (sessionStorage) che mantiene un'area di archiviazione disponibile per la durata della sessione della pagina. Una sessione di pagina dura fino a quando il browser è aperto e sopravvive a ricariche e ripristini di pagine. L'apertura di una pagina in una nuova scheda o finestra comporterà l'avvio di una nuova sessione.

MDN: sessionStorage


1

A beneficio dei ricercatori:

Come Fernando, non volevo aggiungere un carico di json quando i valori memorizzati erano semplici. Avevo solo bisogno di tenere traccia di alcune interazioni dell'interfaccia utente e mantenere i dati pertinenti (ad esempio, come un utente ha utilizzato un sito di e-commerce prima di effettuare il checkout).

Questo non soddisferà i criteri di tutti, ma si spera che sia una copia veloce + incolla un avviatore per qualcuno e salvi l'aggiunta di un'altra lib.

NOTA: ciò non sarebbe utile se è necessario recuperare gli elementi singolarmente.

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

Se hai familiarità con l' oggetto locaStorage del browser , sai che non è previsto un termine di scadenza. Tuttavia, possiamo usare Javascript per aggiungere un TTL (Time to live) per invalidare gli articoli in locaStorage dopo un certo periodo di tempo.

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.