¿Cuándo caducan los elementos en el almacenamiento local HTML5?

338

¿Durante cuánto tiempo están disponibles los datos almacenados en localStorage (como parte del almacenamiento DOM en HTML5)? ¿Puedo establecer un tiempo de vencimiento para los datos que coloco en localStorage?

usuario280427
fuente
3
no use localStorage si es posible porque nunca caduca automáticamente, allí puede usar sessionStorage es más preferible
Dharmendrasinh Chudasama

Respuestas:

216

No es posible especificar la caducidad. Depende completamente del usuario.

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

Por supuesto, es posible que algo que su aplicación almacena en el cliente no esté allí más tarde. El usuario puede deshacerse explícitamente del almacenamiento local, o el navegador puede encontrarse con consideraciones de espacio. Es bueno programar a la defensiva. En general, sin embargo, las cosas permanecen "para siempre" según alguna definición práctica de esa palabra.

editar : obviamente, su propia aplicación puede eliminar cosas activamente si decide que es demasiado antigua. Es decir, puede incluir explícitamente algún tipo de marca de tiempo en lo que ha guardado, y luego usarlo más adelante para decidir si la información se debe eliminar o no.

Puntiagudo
fuente
1
Entonces, ¿puede el usuario contar con los datos disponibles después de, por ejemplo, un año? ¿Puede el desarrollador contar con los datos disponibles a menos que el usuario los elimine explícitamente ?
Andres Riofrio
66
@AndresRiofrio No puedo encontrar ninguna documentación de Mozilla o Microsoft o el W3C que estipule algún tipo de vencimiento obligatorio. Por lo tanto, creo que la respuesta es sí, se supone que el agente de usuario debe mantener las cosas almacenadas para siempre, o hasta que el usuario solicite explícitamente que se eliminen (o supongo que hasta que su propia aplicación elimine sus propias cosas).
Puntiagudo
3
Esto también significa que su navegador sigue creciendo. Usas una aplicación una vez, almacena sus cosas en tu navegador y permanece allí para siempre ...
Pieter van Kampen
1
La cantidad de datos de almacenamiento local que puede almacenar por sitio web es de alrededor de 10 MB, pero un sitio promedio no almacenará mucho más que unas pocas cadenas, por lo que no me importaría el espacio de almacenamiento
Juan
1
Firefox tiene una política de desalojo documentada aquí .
ShreevatsaR
269

Sugeriría almacenar la marca de tiempo en el objeto que almacene en el localStorage

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

Puede analizar el objeto, obtener la marca de tiempo y comparar con la Fecha actual y, si es necesario, actualizar el valor del objeto.

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

compareTime(dateString, now); //to implement
sebarmeli
fuente
3
Bueno, incluso si el tiempo del cliente no es constante, aún puede encontrar una manera de usar el tiempo del servidor. Como hacer eco de la marca de tiempo en un div.
Supreme Dolphin
¿Analizaría y compararía la marca de tiempo en un intervalo de tiempo (por ejemplo, settimoutpor cada 5 segundos) o por cada solicitud que el cliente envíe al servidor?
ibubi el
la mejor manera es comparar fechas para cada solicitud de usuario
Terai
36

Puedes usar lscache . Se encarga de esto automáticamente, incluidas las instancias donde el tamaño de almacenamiento excede el límite. Si eso sucede, comienza a podar los elementos más cercanos a su vencimiento especificado.

De la readme:

lscache.set

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

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

Esta es la única diferencia real entre los métodos de almacenamiento regulares. Obtener, eliminar, etc. funcionan igual.

Si no necesita tanta funcionalidad, simplemente puede almacenar una marca de tiempo con el valor (a través de JSON) y verificar que caduque.

Cabe destacar que hay una buena razón por la cual el almacenamiento local se deja al usuario. Pero, cosas como lscache son útiles cuando necesita almacenar datos extremadamente temporales.

huyz
fuente
¡Gracias! Esto es increíble para lo que necesito: los datos solo deben estar allí en caso de que el usuario haga un booboo o el navegador se cierre antes de guardar su trabajo, pero hay demasiados datos para las cookies. Lo estoy usando junto con pieroxy.net/blog/pages/lz-string/index.html .
Peter Smartt
34

Brynner Ferreira, ha traído un buen punto: almacenar una clave de hermano donde reside la información de caducidad. De esta manera, si tiene una gran cantidad de claves, o si sus valores son objetos Json grandes , no necesita analizarlos para acceder a la marca de tiempo.

aquí sigue una versión mejorada:

 /*  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
fuente
En setStorage (), ¿no debería ser la elselínea expires = Math.abs(1000*expires); //make sure it's positive?
alissonmuller
Solo un punto para la getStoragellamada. Si intenta acceder a la _expiresInversión de la clave directamente, la clave se convierte en la ..._expiresIn_expiresInque, por supuesto, no existe, por lo que elimina la ..._expiresInclave original , y la próxima vez que acceda a la clave original, la clave ..._expiresInno existe y elimina el original. llave. Sugeriría una trampa para eso cuando me topé con esto en uno de mis proyectos. if(key.indexOf('_expiresIn') > -1) { return localStorage.getItem(key); }
akousmata
25

Si bien el almacenamiento local no proporciona un mecanismo de caducidad, las cookies sí. Simplemente emparejar una clave de almacenamiento local con una cookie proporciona una manera fácil de garantizar que el almacenamiento local se pueda actualizar con los mismos parámetros de caducidad que una cookie.

Ejemplo en 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

Este ejemplo establece que una cookie con el parámetro predeterminado caduque cuando se cierra el navegador. Por lo tanto, cuando el navegador se cierra y se vuelve a abrir, una llamada del lado del servidor actualiza el almacén de datos local para your_data.

Tenga en cuenta que esto no es exactamente lo mismo que eliminar el almacén de datos local, sino que está actualizando el almacén de datos local cada vez que caduca la cookie. Sin embargo, si su objetivo principal es poder almacenar más de 4K en el lado del cliente (la limitación para el tamaño de la cookie), este emparejamiento de cookies y almacenamiento local lo ayudará a lograr un mayor tamaño de almacenamiento utilizando los mismos parámetros de caducidad que una cookie .

Robert Peake
fuente
Las cookies se pueden eliminar y, lo que es peor, se pueden desactivar por completo.
Supreme Dolphin
1
Esta solución me gusta más porque permite que el navegador maneje el vencimiento de nuestra solución de almacenamiento sin tener que usar otras bibliotecas o administrar manualmente las fechas de almacenamiento local.
ecc
10
Tenga en cuenta que las cookies se envían en CADA solicitud.
Lucas Freitas
24

Aquí muy recomendable utilizar sessionStorage

  • es igual que localStorage pero se destruye cuando se destruye la sesión / se cierra el navegador
  • también localStorage puede compartir entre pestañas, mientras que sessionStorage puede usar solo en la pestaña actual, pero el valor no cambia en la página de actualización ni cambia la página
  • sessionStorage también es útil para reducir el tráfico de red contra cookies

para uso de valor establecido

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

para obtener valor de uso

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

haga clic aquí para ver la api

todas las formas de establecer son

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

todas las formas de obtener son

  var value = sessionStorage.key;
  var value = sessionStorage["key"];
  var value = sessionStorage.getItem("key");
Dharmendrasinh Chudasama
fuente
8
Tenga en cuenta que sessionStorageno funciona compartir datos entre pestañas
Bhargava Mummadireddy
15

El ciclo de vida es controlado por la aplicación / usuario.

De la norma :

Los agentes de usuario deben expirar los datos de las áreas de almacenamiento local solo por razones de seguridad o cuando el usuario lo solicite. Los agentes de usuario siempre deben evitar eliminar datos mientras se ejecuta un script que podría acceder a esos datos.

jldupont
fuente
11

Del borrador del W3C:

Los agentes de usuario deben expirar los datos de las áreas de almacenamiento local solo por razones de seguridad o cuando el usuario lo solicite. Los agentes de usuario siempre deben evitar eliminar datos mientras se ejecuta un script que podría acceder a esos datos.

Querrá hacer sus actualizaciones en su horario usando setItem (clave, valor); eso agregará o actualizará la clave dada con los nuevos datos.

Padre tormenta
fuente
Hmm ... ¿quizás sería una buena idea incluir una fecha como parte de los datos? O tal vez usando una clave diferente cada vez que cambian los datos.
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
fuente
44
Me gusta este enfoque, ya que no requiere analizar primero los datos.
Christophe
3

Si alguien usa jStorage Plugin de jQuery, se puede agregar caducidad con la función setTTL si jStorage plugin

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

Si alguien sigue buscando una solución rápida y no quiere dependencias como jquery, etc., escribí una mini lib que agrega caducidad al almacenamiento local / sesión / personalizado, puede encontrarla con la fuente aquí:

https://github.com/RonenNess/ExpiredStorage

Ronen Ness
fuente
3

Puedes probar este.

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
fuente
1

Solución alternativa con almacenamiento angular y local:

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

})
Tomás Romero
fuente
Revisé el sitio y no veo ninguna clave 'expireTimeInMilliseconds' en su API. ¿Es una configuración no documentada / no admitida?
aaaaaa
1
@PhilOlson es una implementación personalizada que he usado localforage. expireTimeInMillisecondsno es un localforageatributo, sino una variable que he usado para verificar si los datos almacenados deben expirar Verifique la getdefinición de la función en mi ejemplo.
Tomás Romero
wow localforageno es la clase de ayudante ligera que esperaba
Simon_Weaver
1

El enfoque de @ sebarmeli es el mejor en mi opinión, pero si solo desea que los datos persistan durante la vida de una sesión, entonces sessionStorageprobablemente sea una mejor opción:

Este es un objeto global (sessionStorage) que mantiene un área de almacenamiento disponible durante la sesión. Una sesión de página dura mientras el navegador esté abierto y sobreviva a la recarga y restauración de la página. Al abrir una página en una nueva pestaña o ventana, se iniciará una nueva sesión.

MDN: sessionStorage

Kevin Leary
fuente
1

En beneficio de los buscadores:

Al igual que Fernando, no quería agregar una carga de json cuando los valores almacenados eran simples. Solo necesitaba rastrear cierta interacción de la interfaz de usuario y mantener los datos relevantes (por ejemplo, cómo un usuario utilizó un sitio de comercio electrónico antes de pagar).

Esto no cumplirá con los criterios de todos, pero esperamos que sea un inicio rápido de copiar + pegar para alguien y guardar agregando otra lib.

NOTA: Esto no sería bueno si necesita recuperar los elementos individualmente.

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

Si está familiarizado con el objeto locaStorage de los navegadores , sabe que no hay ninguna disposición para proporcionar un tiempo de caducidad. Sin embargo, podemos usar Javascript para agregar un TTL (Tiempo de vida) para invalidar elementos en locaStorage después de un cierto período de tiempo.

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
fuente