Quand les éléments du stockage local HTML5 expirent-ils?

338

Pendant combien de temps les données stockées dans localStorage (dans le cadre du stockage DOM en HTML5) sont-elles disponibles? Puis-je définir un délai d'expiration pour les données que je place dans localStorage?

user280427
la source
3
n'utilisez pas localStorage si possible parce qu'il n'expire jamais automatiquement, là vous pouvez utiliser sessionStorage c'est plus préférable
Dharmendrasinh Chudasama

Réponses:

216

Il n'est pas possible de spécifier l'expiration. C'est entièrement à l'utilisateur.

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

Bien sûr, il est possible que quelque chose que votre application stocke sur le client ne soit pas là plus tard. L'utilisateur peut explicitement se débarrasser du stockage local, ou le navigateur peut rencontrer des considérations d'espace. C'est bon de programmer défensivement. Généralement, cependant, les choses restent "pour toujours" sur la base d'une définition pratique de ce mot.

modifier - évidemment, votre propre application peut supprimer activement des éléments si elle décide qu'elle est trop ancienne. Autrement dit, vous pouvez explicitement inclure une sorte d'horodatage dans ce que vous avez enregistré, puis l'utiliser plus tard pour décider si les informations doivent être vidées ou non.

Pointu
la source
1
L'utilisateur peut-il donc compter sur les données disponibles après, disons, un an? Le développeur peut-il compter sur les données disponibles à moins que l'utilisateur ne les supprime explicitement ?
Andres Riofrio
6
@AndresRiofrio Je ne trouve aucune documentation de Mozilla ou de Microsoft ou du W3C qui stipule toute sorte d'expiration obligatoire. Ainsi, je pense que la réponse est que oui, l'agent utilisateur est censé conserver les informations stockées pour toujours, ou jusqu'à ce que l'utilisateur demande explicitement qu'elles soient supprimées (ou je suppose que votre propre application supprime ses propres informations).
Pointy
3
Cela signifie également que votre navigateur ne cesse de croître. Vous utilisez une application une fois, elle stocke ses éléments dans votre navigateur, et elle y reste pour toujours ....
Pieter van Kampen
1
La quantité de données localStorage vous pouvez stocker par site est d' environ 10 Mo, mais un magasin wont moyenne du site beaucoup plus que quelques cordes, donc je wouldnt esprit de l' espace de stockage
Juan
1
Firefox a une politique d'expulsion documentée ici .
ShreevatsaR
269

Je suggère de stocker l'horodatage dans l' objet que vous stockez dans le localStorage

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

Vous pouvez analyser l'objet, obtenir l'horodatage et comparer avec la date actuelle et, si nécessaire, mettre à jour la valeur de l'objet.

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

compareTime(dateString, now); //to implement
sebarmeli
la source
3
Eh bien, même si l'heure du client n'est pas cohérente, vous pouvez toujours trouver un moyen d'utiliser l'heure de votre serveur à la place. Comme faire écho à l'horodatage en div.
Supreme Dolphin
Souhaitez-vous analyser et comparer l'horodatage dans un intervalle de temps (par exemple settimouttoutes les 5 secondes) ou pour chaque demande que le client envoie au serveur?
ibubi
la meilleure façon est de comparer les dates pour chaque demande de l'utilisateur
Terai
36

Vous pouvez utiliser lscache . Il gère cela automatiquement pour vous, y compris les cas où la taille de stockage dépasse la limite. Si cela se produit, il commence l'élagage des éléments les plus proches de leur date d'expiration spécifiée.

Du readme:

lscache.set

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

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

C'est la seule vraie différence entre les méthodes de stockage habituelles. Get, remove, etc fonctionnent de la même manière.

Si vous n'avez pas besoin de beaucoup de fonctionnalités, vous pouvez simplement stocker un horodatage avec la valeur (via JSON) et vérifier son expiration.

Il convient de noter qu'il existe une bonne raison pour laquelle le stockage local est laissé à l'utilisateur. Mais, des choses comme lscache sont utiles lorsque vous devez stocker des données extrêmement temporaires.

huyz
la source
Je vous remercie! C'est génial pour ce dont j'ai besoin - les données doivent simplement être là au cas où l'utilisateur fait un booboo ou le navigateur se ferme avant d'avoir enregistré son travail, mais il y a trop de données pour les cookies. Je l'utilise conjointement avec pieroxy.net/blog/pages/lz-string/index.html .
Peter Smartt
34

Brynner Ferreira, a apporté un bon point: stocker une clé de frère où réside les informations d'expiration. De cette façon, si vous avez un grand nombre de clés ou si vos valeurs sont de gros objets Json , vous n'avez pas besoin de les analyser pour accéder à l'horodatage.

voici une version améliorée:

 /*  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
la source
Dans setStorage (), la elseligne ne devrait-elle pas l' être expires = Math.abs(1000*expires); //make sure it's positive?
alissonmuller
Juste un point pour l' getStorageappel. Si vous essayez d'accéder _expiresIndirectement à la version de la clé, la clé devient alors celle ..._expiresIn_expiresInqui n'existe bien sûr pas, donc elle supprime la ..._expiresInclé d' origine , puis la prochaine fois que vous accédez à la clé d'origine, la ..._expiresInn'existe pas et elle supprime l'original clé. Je suggérerais de piéger cela alors que je rencontrais cela dans l'un de mes projets. if(key.indexOf('_expiresIn') > -1) { return localStorage.getItem(key); }
akousmata
25

Alors que le stockage local ne fournit pas de mécanisme d'expiration, les cookies le font. Le simple fait d'associer une clé de stockage locale à un cookie permet de s'assurer que le stockage local peut être mis à jour avec les mêmes paramètres d'expiration qu'un cookie.

Exemple dans 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

Cet exemple définit un cookie dont le paramètre par défaut expire lorsque le navigateur est fermé. Ainsi, lorsque le navigateur est fermé et rouvert, le magasin de données local pour vos_données est actualisé par un appel côté serveur.

Notez que ce n'est pas exactement la même chose que de supprimer le magasin de données local, il s'agit plutôt de mettre à jour le magasin de données local chaque fois que le cookie expire. Cependant, si votre objectif principal est de pouvoir stocker plus de 4K côté client (la limitation de la taille des cookies), cette association de cookie et de stockage local vous aidera à atteindre une taille de stockage plus grande en utilisant les mêmes paramètres d'expiration qu'un cookie .

Robert Peake
la source
Les cookies peuvent être effacés et, pire encore, peuvent être complètement désactivés.
Supreme Dolphin du
1
J'aime le plus cette solution, car elle permet au navigateur de gérer l'expiration de notre solution de stockage sans avoir à utiliser d'autres bibliothèques ou à gérer manuellement les dates de stockage local.
ecc
10
Gardez à l'esprit que les cookies sont envoyés à CHAQUE demande.
Lucas Freitas
24

Voici fortement recommandé d'utiliser sessionStorage

  • il est identique à localStorage mais détruit lorsque la session est détruite / fermeture du navigateur
  • localStorage peut également partager entre les onglets tandis que sessionStorage peut utiliser uniquement dans l'onglet actuel, mais la valeur ne change pas sur la page d'actualisation ou change la page
  • sessionStorage est également utile pour réduire le trafic réseau contre les cookies

pour l'utilisation de la valeur définie

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

pour obtenir une valeur ajoutée

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

cliquez ici pour voir l'api

toutes les façons de définir sont

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

toutes les façons d'obtenir sont

  var value = sessionStorage.key;
  var value = sessionStorage["key"];
  var value = sessionStorage.getItem("key");
Dharmendrasinh Chudasama
la source
8
Notez que sessionStoragecela ne fonctionne pas pour partager des données entre les onglets
Bhargava Mummadireddy
15

Le cycle de vie est contrôlé par l'application / l'utilisateur.

De la norme :

Les agents utilisateurs ne doivent expirer les données des zones de stockage locales que pour des raisons de sécurité ou à la demande de l'utilisateur. Les agents utilisateurs doivent toujours éviter de supprimer des données pendant l'exécution d'un script pouvant accéder à ces données.

jldupont
la source
11

Du projet du W3C:

Les agents utilisateurs ne doivent expirer les données des zones de stockage locales que pour des raisons de sécurité ou à la demande de l'utilisateur. Les agents utilisateurs doivent toujours éviter de supprimer des données pendant l'exécution d'un script pouvant accéder à ces données.

Vous voudrez faire vos mises à jour sur votre calendrier en utilisant setItem (clé, valeur); qui ajoutera ou mettra à jour la clé donnée avec les nouvelles données.

FatherStorm
la source
Hmm ... peut-être que lister une date dans les données serait une bonne idée? Ou peut-être en utilisant une clé différente chaque fois que les données changent.
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
la source
4
J'aime cette approche, car elle ne nécessite pas d'analyser les données en premier.
Christophe
3

Si quelqu'un utilise le plugin jStorage de jQuery, il peut être ajouter une expiration avec la fonction setTTL si le plugin jStorage

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

Si quelqu'un cherche toujours une solution rapide et ne veut pas de dépendances comme jquery etc. J'ai écrit une mini lib qui ajoute l'expiration au stockage local / session / personnalisé, vous pouvez le trouver avec la source ici:

https://github.com/RonenNess/ExpiredStorage

Ronen Ness
la source
3

Vous pouvez essayer celui-ci.

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
la source
1

Solution de contournement utilisant le fourrage angulaire et 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
        }
      })
    }
  }

})
Tomas Romero
la source
J'ai vérifié le site et je ne vois aucune clé «expireTimeInMilliseconds» dans leur API. S'agit-il d'un paramètre non documenté / non pris en charge?
aaaaaa
1
@PhilOlson c'est une implémentation personnalisée que j'ai utilisée en utilisant localforage. expireTimeInMillisecondsn'est pas un localforageattribut, mais une variable que j'ai utilisée pour vérifier si les données stockées doivent expirer. Vérifiez la getdéfinition de la fonction sur mon exemple.
Tomas Romero
wow localforagen'est pas la petite classe d'aide légère que j'attendais
Simon_Weaver
1

L'approche de @ sebarmeli est la meilleure à mon avis, mais si vous voulez que les données persistent pendant toute la durée d'une session, sessionStoragec'est probablement une meilleure option:

Il s'agit d'un objet global (sessionStorage) qui gère une zone de stockage disponible pendant la durée de la session de page. Une session de page dure aussi longtemps que le navigateur est ouvert et survit pendant les rechargements et les restaurations de pages. L'ouverture d'une page dans un nouvel onglet ou une nouvelle fenêtre entraînera le lancement d'une nouvelle session.

MDN: sessionStorage

Kevin Leary
la source
1

Pour le bénéfice des chercheurs:

Comme Fernando, je ne voulais pas ajouter une charge de json lorsque les valeurs stockées étaient simples. J'avais juste besoin de suivre certaines interactions de l'interface utilisateur et de garder les données pertinentes (par exemple, comment un utilisateur a utilisé un site de commerce électronique avant de vérifier).

Cela ne répondra pas aux critères de tout le monde, mais sera, espérons-le, un démarreur rapide de copier-coller pour quelqu'un et d'économiser en ajoutant une autre bibliothèque.

REMARQUE: ce ne serait pas bon si vous devez récupérer les éléments individuellement.

// 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
la source
0

Si vous connaissez l' objet locaStorage des navigateurs , vous savez qu'il n'y a aucune disposition pour fournir une heure d'expiration. Cependant, nous pouvons utiliser Javascript pour ajouter un TTL (Time to live) pour invalider les éléments dans locaStorage après un certain laps de temps.

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
la source