Quando os itens no armazenamento local HTML5 expiram?

336

Por quanto tempo os dados armazenados no localStorage (como parte do DOM Storage em HTML5) estão disponíveis? Posso definir um tempo de expiração para os dados que coloco no localStorage?

user280427
fonte
3
não usar localStorage se possível, porque nunca é expiram automaticamente, lá você pode usar sessionStorage é mais preferível
Dharmendrasinh Chudasama

Respostas:

215

Não é possível especificar a expiração. Depende completamente do usuário.

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

Obviamente, é possível que algo que seu aplicativo armazena no cliente possa não estar lá mais tarde. O usuário pode se livrar explicitamente do armazenamento local ou o navegador pode se deparar com considerações de espaço. É bom programar defensivamente. Geralmente, porém, as coisas permanecem "para sempre" com base em alguma definição prática dessa palavra.

editar - obviamente, seu próprio aplicativo pode remover coisas ativamente se decidir que é muito antigo. Ou seja, você pode incluir explicitamente algum tipo de carimbo de data / hora no que foi salvo e depois usá-lo posteriormente para decidir se as informações devem ou não ser liberadas.

Pontudo
fonte
11
Então, o usuário pode contar com os dados disponíveis após, digamos, um ano? O desenvolvedor pode contar com os dados disponíveis, a menos que o usuário os exclua explicitamente ?
Andres Riofrio
6
@AndresRiofrio Não consigo encontrar nenhuma documentação da Mozilla, Microsoft ou W3C que estipule qualquer tipo de expiração obrigatória. Portanto, acho que a resposta é que sim, o agente do usuário deve manter o material armazenado para sempre, ou até que o usuário solicite explicitamente que ele seja excluído (ou acho que até que seu próprio aplicativo exclua seu próprio material).
Pointy
3
Isso também significa que seu navegador continua crescendo. Você usa um aplicativo uma vez, ele armazena-lo de coisas no seu browser, e ele permanece lá para sempre ....
Pieter van Kampen
11
A quantidade de dados localStorage você pode armazenar per site é de cerca de 10MB, mas um costume média loja local muito mais do que algumas cordas, então eu não me importaria com espaço de armazenamento
Juan
11
O Firefox tem uma política de despejo documentada aqui .
ShreevatsaR
269

Sugiro que você armazene o registro de data e hora no objeto que você armazena no localStorage

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

Você pode analisar o objeto, obter o carimbo de data e hora e comparar com a Data atual e, se necessário, atualizar o valor do objeto.

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

compareTime(dateString, now); //to implement
sebarmeli
fonte
3
Bem, mesmo que o horário do cliente não seja consistente, você ainda poderá encontrar uma maneira de usar o horário do servidor. Como ecoar o timestamp em uma div.
Supreme Dolphin
Você analisaria e compararia o registro de data e hora em um intervalo de tempo (por exemplo, settimouta cada 5 segundos) ou para cada solicitação que o cliente envia ao servidor?
ibubi 23/10
a melhor maneira é comparar as datas para cada solicitação do usuário
Terai
36

Você pode usar o lscache . Ele lida com isso automaticamente, incluindo instâncias em que o tamanho do armazenamento excede o limite. Se isso acontecer, ele inicia a remoção dos itens mais próximos da expiração especificada.

De readme:

lscache.set

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

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

Essa é a única diferença real entre os métodos regulares de armazenamento. Obter, remover, etc. funcionam da mesma maneira.

Se você não precisar de tanta funcionalidade, poderá simplesmente armazenar um carimbo de data / hora com o valor (via JSON) e verificar a validade.

Digno de nota, há uma boa razão pela qual o armazenamento local é deixado para o usuário. Porém, coisas como lscache são úteis quando você precisa armazenar dados extremamente temporários.

huyz
fonte
Obrigado! Isso é incrível para o que eu preciso - os dados só precisam estar disponíveis caso o usuário faça um booboo ou o navegador seja fechado antes de salvar seu trabalho, mas há muitos dados para cookies. Estou usando-o em conjunto com pieroxy.net/blog/pages/lz-string/index.html .
22816 Peter Smartt #
34

Brynner Ferreira, trouxe um bom ponto: armazenar uma chave de irmão onde as informações de expiração residem. Dessa forma, se você tiver uma grande quantidade de chaves ou se seus valores forem objetos Json grandes , não será necessário analisá-los para acessar o registro de data e hora.

aqui segue uma versão melhorada:

 /*  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
fonte
Em setStorage (), a elselinha não deveria ser expires = Math.abs(1000*expires); //make sure it's positive?
Alissonmuller 29/04
Apenas um ponto para a getStorageligação. Se você tentar acessar _expiresIndiretamente a versão da chave, a chave se tornará a ..._expiresIn_expiresInque obviamente não existe, removendo a ..._expiresInchave original e, na próxima vez em que você acessar a chave original, a chave ..._expiresInnão existir e a original será excluída. chave. Eu sugeriria uma armadilha para isso, quando me deparei com isso em um dos meus projetos. if(key.indexOf('_expiresIn') > -1) { return localStorage.getItem(key); }
akousmata 8/07/19
24

Enquanto o armazenamento local não fornece um mecanismo de expiração, os cookies fornecem. Simplesmente emparelhar uma chave de armazenamento local com um cookie fornece uma maneira fácil de garantir que o armazenamento local possa ser atualizado com os mesmos parâmetros de expiração que um cookie.

Exemplo no 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 exemplo define um cookie com o parâmetro padrão para expirar quando o navegador é fechado. Portanto, quando o navegador é fechado e reaberto, o armazenamento de dados local para seus_dados é atualizado por uma chamada do servidor.

Observe que isso não é exatamente o mesmo que remover o armazenamento de dados local; em vez disso, atualiza o armazenamento de dados local sempre que o cookie expirar. No entanto, se seu objetivo principal é armazenar mais de 4K no lado do cliente (a limitação do tamanho do cookie), esse pareamento de cookie e armazenamento local ajudará você a obter um tamanho de armazenamento maior usando os mesmos parâmetros de expiração que um cookie .

Robert Peake
fonte
Os cookies podem ser limpos e, pior ainda, podem ser completamente desativados.
Supreme Dolphin
11
Gosto mais desta solução porque permite que o navegador lide com a expiração de nossa solução de armazenamento sem precisar usar outras bibliotecas ou gerenciar manualmente as datas de armazenamento local.
ECC
10
Lembre-se de que os cookies são enviados em TODAS as solicitações.
Lucas Freitas
24

Aqui é altamente recomendável usar o sessionStorage

  • é o mesmo que localStorage, mas destrói quando a sessão é destruída / o navegador é fechado
  • também localStorage pode compartilhar entre guias, enquanto o sessionStorage pode ser usado somente na guia atual, mas o valor não muda na página de atualização nem na página
  • sessionStorage também é útil para reduzir o tráfego de rede contra cookies

para uso de valor definido

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

para obter valor use

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

clique aqui para ver a API

todas as maneiras de definir são

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

todas as maneiras de obter são

  var value = sessionStorage.key;
  var value = sessionStorage["key"];
  var value = sessionStorage.getItem("key");
Dharmendrasinh Chudasama
fonte
8
Note-se que sessionStoragenão funciona para compartilhar dados entre as abas
Bhargava Mummadireddy
14

O ciclo de vida é controlado pelo aplicativo / usuário.

Do padrão :

Os agentes do usuário devem expirar os dados das áreas de armazenamento local apenas por motivos de segurança ou quando solicitados pelo usuário. Os agentes do usuário sempre devem evitar a exclusão de dados enquanto um script que pode acessar esses dados estiver em execução.

jldupont
fonte
10

A partir do rascunho do W3C:

Os agentes do usuário devem expirar os dados das áreas de armazenamento local apenas por motivos de segurança ou quando solicitados pelo usuário. Os agentes do usuário sempre devem evitar a exclusão de dados enquanto um script que pode acessar esses dados estiver em execução.

Você desejará fazer suas atualizações em sua programação usando setItem (key, value); que adicionará ou atualizará a chave fornecida com os novos dados.

FatherStorm
fonte
Hmm ... talvez listar uma data como parte dos dados seria uma boa ideia? Ou talvez usando uma chave diferente sempre que os dados forem alterados.
usar o seguinte
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
fonte
4
Eu gosto dessa abordagem, pois não requer a análise dos dados primeiro.
Christophe
3

Se alguém usando o jStorage Plugin do jQuery, pode adicionar a validade com a função setTTL se o jStorage plugin

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

Se alguém ainda procura uma solução rápida e não quer dependências como jquery, etc. Escrevi uma mini-lib que adiciona expiração ao armazenamento local / sessão / personalizado, você pode encontrá-lo com a fonte aqui:

https://github.com/RonenNess/ExpiredStorage

Ronen Ness
fonte
3

Você pode tentar 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
fonte
1

Solução alternativa usando forragem angular e 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
fonte
Eu verifiquei o site e não vejo nenhuma chave 'expireTimeInMilliseconds' em sua API. É uma configuração não documentada / não suportada?
aaaaaa
11
@PhilOlson é uma implementação personalizada que usei localforage. expireTimeInMillisecondsnão é um localforageatributo, mas uma variável que eu usei para verificar se os dados armazenados precisam expirar. Verifique a getdefinição da função no meu exemplo.
Tomas Romero
wow localforagenão é a classe auxiliar pouco leve eu estava esperando
Simon_Weaver
1

A abordagem de @ sebarmeli é a melhor na minha opinião, mas se você deseja que os dados persistam durante toda a vida de uma sessão, sessionStorageprovavelmente é uma opção melhor:

Este é um objeto global (sessionStorage) que mantém uma área de armazenamento disponível durante a sessão da página. Uma sessão de página dura enquanto o navegador estiver aberto e sobreviver durante as recargas e restaurações da página. Abrir uma página em uma nova guia ou janela fará com que uma nova sessão seja iniciada.

MDN: sessionStorage

Kevin Leary
fonte
1

Para o benefício dos pesquisadores:

Como Fernando, eu não queria adicionar uma carga de json quando os valores armazenados eram simples. Eu só precisava acompanhar alguma interação da interface do usuário e manter os dados relevantes (por exemplo, como um usuário usou um site de comércio eletrônico antes de fazer o check-out).

Isso não atenderá aos critérios de todos, mas espero que seja uma cópia rápida e uma pasta para alguém e salve a adição de outra biblioteca.

NOTA: Isso não seria bom se você precisar recuperar os itens 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
fonte
0

Se você estiver familiarizado com o objeto locaStorage dos navegadores , sabe que não há previsão de prazo de validade. No entanto, podemos usar o Javascript para adicionar um TTL (tempo de vida) para invalidar itens no locaStorage após um certo período de 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;
}
iProDev
fonte