Como excluir um item localStorage quando a janela / guia do navegador está fechada?


403

Meu caso: localStorage com chave + valor que deve ser excluído quando o navegador estiver fechado e não em uma única guia.

Por favor, veja meu código se for adequado e o que pode ser melhorado:

//create localStorage key + value if not exist
if(localStorage){
   localStorage.myPageDataArr={"name"=>"Dan","lastname"=>"Bonny"}; 
}

//when browser closed - psedocode
$(window).unload(function(){
  localStorage.myPageDataArr=undefined;
});

32
Se você deseja limpar o armazenamento local ao fechar o navegador, questiono seus motivos para usá-lo.
Dunhamzzz 30/03/12

16
Você pode ter objetos de armazenamento local e de sessão - eu usaria sessionStorage para valores de sessão. Btw, definir um valor como indefinido não o exclui ou o remove do localStorage, apenas define seu valor como indefinido.
Kennebec

2
@kennebec - Definir como undefinedsobrescreveria o item armazenado anteriormente. Mas sim, usar .removeItem()é mais apropriado.
Nnnnnn 12/10

2
basta usar sessionStorage vez de localStorage
Alberto Acuña

2
Use localStorage.clear(); se você quiser limpar todo o armazenamento.
Black Mamba

Respostas:


802

deve ser feito assim e não com o operador delete:

localStorage.removeItem(key);

11
Por que não podemos usar exatamente o operador de exclusão? Dos meus testes, parece que delete localStorage.keyfunciona tão bem quanto localStorage.removeItem(key). Parece mais claro para mim usar delete quando eu definir minhas variáveis ​​como em localStorage.key = 1vez de localStorage.setItem('key', 1).
Aust

6
Se funcionar, você pode usá-lo tecnicamente. Mas, considerando que removeItem é fornecido como uma função de membro, parece lógico usá-lo em vez de executar um comportamento potencialmente indefinido usando um operador separado.
kungphu

@kungphu tenha em mente que sempre é possível (acidentalmente) fazer localStorage.removeItem = null;, criando localStorage.removeItem(key);uma ideia potencialmente ruim.
Skeggse

31
Não vejo como é uma contingência razoável para planejar. O fato de uma linguagem permitir que as pessoas façam coisas destrutivas não significa que você deve adotar maneiras não padronizadas de usar bibliotecas como defesa contra o uso indevido da linguagem. Se você ou seus colegas desenvolvedores não entenderem a diferença entre invocação e designação, você terá problemas muito maiores do que a melhor maneira de remover itens do localStorage.
kungphu

3
@skeggse é exatamente por isso que é uma má idéia para escrever localStorage.key = 1em primeiro lugar - para evitar este tipo de acidentes
Jivan

114

Use com windowa palavra-chave global: -

 window.localStorage.removeItem('keyName');

6
por que usar o objeto janela? simplesmente localStorage.removeItem(key)funciona bem.
Pardeep Jain


Esta solução realmente funciona para o IE 11? Por favor sugira. Estou tendo esse problema no código angular 5.
Karan

95

Você pode fazer uso do beforeunloadevento em JavaScript.

Usando o vanilla JavaScript, você pode fazer algo como:

window.onbeforeunload = function() {
  localStorage.removeItem(key);
  return '';
};

Isso excluirá a chave antes que a janela / guia do navegador seja fechada e solicitará que você confirme a ação de fechar a janela / guia. Espero que isso resolva seu problema.

NOTA: O onbeforeunloadmétodo deve retornar uma string.


Isso foi realmente útil. Pode ser bom aceitar a resposta (mesmo depois de todo esse tempo).
Richard Morgan

8
@dhsto VanillaJS é JavaScript simples :) Veja aqui: O que é VanillaJS? .
Bharat Khatri

11
Um problema é que isso é chamado mesmo se você navegar na mesma página, não apenas quando a guia estiver fechada, o que pode não ser o que se destina. Nota lateral: retornar indefinido de onbeforeunload desativará a mensagem exibida ao descarregar.
9788 Stanley

O que aconteceu se o usuário quiser permanecer na página e você já excluir o armazenamento local? Além disso, a solução não está trabalhando no Chrome e IE11
oracleruiz

Por que não usar sessionStorage então?
Sachin Prasad

94

Você deve usar o sessionStorage se desejar que a chave seja excluída quando o navegador fechar.


3
Esta é a melhor resposta; sessionStorageé o remédio para o que o solicitante descreve.
Benny

8
+1 para mencionar sessionStorage, mas o Rascunho do Editor W3C diz: 'O tempo de vida de um contexto de navegação pode não estar relacionado ao tempo de vida do processo real do agente do usuário, pois ele pode suportar a retomada de sessões após uma reinicialização.'
Tamás

28
O problema com 'sessionStorage' é que ele não é armazenado quando você abre uma nova guia, por exemplo, com a tecla Ctrl pressionada em um link. Preciso de um híbrido localStorage / sessionStorage lol.
Edwin Stoteler

3
@EdwinStoteler Me também. Estou meio confuso com o que eles estavam pensando quando o projetaram dessa maneira. Eu realmente preciso acessar essencialmente um armazenamento de navegador somente na memória que é destruído quando o navegador é fechado. Quero armazenar informações confidenciais de uma maneira que possa ser acessada em todo um domínio, mas não quero que essas informações atinjam nenhum disco rígido.
BT

19

Tente usar

$(window).unload(function(){
  localStorage.clear();
});

Espero que funcione para voce


2
você deseja limpar o localStorage completo? se for o caso, use #localStorage.clear();
Rafael Marques

sua foi claro o que eu quero em questão - chave único valor + DELETE
Yosef

12
Isso limpará todo o armazenamento local. má solução!
Emmy

12

Há um caso de uso muito específico no qual qualquer sugestão para usar sessionStorage em vez de localStorage realmente não ajuda. O caso de uso seria algo tão simples quanto ter algo armazenado enquanto você tiver pelo menos uma guia aberta, mas a invalidará se você fechar a última guia restante. Se você precisar que seus valores sejam salvos em guias e janelas, o sessionStorage não o ajudará, a menos que você complique sua vida com os ouvintes, como eu tentei. Enquanto isso, o localStorage seria perfeito para isso, mas faz o trabalho "muito bem", pois seus dados estarão esperando lá, mesmo após a reinicialização do navegador. Acabei usando um código e uma lógica personalizados que aproveitam os dois.

Prefiro explicar do que dar código. Primeiro armazene o que você precisa no localStorage e, em seguida, também no localStorage, crie um contador que conterá o número de guias que você abriu. Isso será aumentado toda vez que a página for carregada e diminuído toda vez que a página for descarregada. Você pode escolher aqui os eventos a serem usados, eu sugiro 'carregar' e 'descarregar'. No momento em que você descarrega, você precisa executar as tarefas de limpeza que deseja quando o contador chegar a 0, o que significa que você está fechando a última guia. Aí vem a parte complicada: eu não encontrei uma maneira confiável e genérica de diferenciar uma recarga ou navegação de página dentro da página e o fechamento da guia. Portanto, se os dados armazenados não forem algo que você possa reconstruir em carga após verificar se esta é sua primeira guia, não será possível removê-lo a cada atualização. Em vez disso, você precisa armazenar um sinalizador no sessionStorage a cada carregamento antes de aumentar o contador de guias. Antes de armazenar esse valor, você pode verificar se ele já possui um valor e, caso contrário, isso significa que você está carregando nesta sessão pela primeira vez, o que significa que você pode fazer a limpeza em carga, se isso o valor não está definido e o contador é 0.


Como resposta ao "por que não usar o sessionStorage?" abordagem, também de w3schools.com/html/html5_webstorage.asp : "window.sessionStorage - armazena dados para uma sessão (os dados são perdidos quando a guia é fechada)". Então a resposta é exatamente isso. sessionStorage é inútil se você quiser algo persistente, mesmo no caso de uso que descrevi.
Solthun 13/03/2015

3
Eu estou pensando que a melhor implementação para isso seria um serviço browserWatcher que basicamente dispara eventos que outros componentes podem ouvir (por exemplo, abrir o navegador, fechar o navegador, carregar o broswer, carregar o descarregador etc.) e ocultar todos esses detalhes de implementação dentro dele Cada componente pode decidir com quais eventos ele precisa lidar para realizar seu trabalho. Minha única pergunta seria o que acontece se a energia for cortada na máquina ou algo assim, essas propriedades permanecerão em localStorage na próxima vez em que o navegador for aberto. ?
pQuestions123

11

use sessionStorage

O objeto sessionStorage é igual ao objeto localStorage, exceto que ele armazena os dados para apenas uma sessão. Os dados são excluídos quando o usuário fecha a janela do navegador.

O exemplo a seguir conta o número de vezes que um usuário clicou em um botão na sessão atual:

Exemplo

if (sessionStorage.clickcount) {
    sessionStorage.clickcount = Number(sessionStorage.clickcount) + 1;
} else {
    sessionStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "You have clicked the button " +
sessionStorage.clickcount + " time(s) in this session.";

11
Os dados são excluídos na aba do navegador.
Kosmonaft 20/09/18

7
for (let i = 0; i < localStorage.length; i++) {
    if (localStorage.key(i).indexOf('the-name-to-delete') > -1) {
        arr.push(localStorage.key(i));
    }
}

for (let i = 0; i < arr.length; i++) {
    localStorage.removeItem(arr[i]);
}

5
localStorage.removeItem(key);  //item

localStorage.clear(); //all items

11
Ao responder a uma pergunta antiga, sua resposta seria muito mais útil para outros usuários do StackOverflow se você incluísse algum contexto para explicar como sua resposta ajuda, principalmente para uma pergunta que já tenha uma resposta aceita. Veja: Como escrevo uma boa resposta .
Tân

Parece claro o suficiente para mim
Giorgio Tempesta

4

Embora alguns usuários já tenham respondido a essa pergunta, estou fornecendo um exemplo de configurações de aplicativo para resolver esse problema.

Eu tive o mesmo problema. Estou usando o módulo https://github.com/grevory/angular-local-storage no meu aplicativo angularjs. Se você configurar seu aplicativo da seguinte maneira, ele salvará a variável no armazenamento da sessão em vez do armazenamento local. Portanto, se você fechar o navegador ou a guia, o armazenamento da sessão será removido automaticamente. Você não precisa fazer nada.

app.config(function (localStorageServiceProvider) {
  localStorageServiceProvider
  .setPrefix('myApp')
  .setStorageType('sessionStorage')
});

Espero que ajude.


4

Existem cinco métodos para você escolher:

  • setItem (): adiciona chave e valor ao localStorage
  • getItem (): recupera um valor pela chave de localStorage
  • removeItem (): remove um item por chave do localStorage
  • clear (): Limpar tudo localStorage
  • key (): passou um número para recuperar a enésima chave de um localStorage

Você pode usar clear (), esse método, quando chamado, limpa todo o armazenamento de todos os registros desse domínio. Não recebe nenhum parâmetro.

window.localStorage.clear();

3

Aqui está um teste simples para verificar se você possui suporte ao navegador ao trabalhar com armazenamento local:

if(typeof(Storage)!=="undefined") {
  console.log("localStorage and sessionStorage support!");
  console.log("About to save:");
  console.log(localStorage);
  localStorage["somekey"] = 'hello';
  console.log("Key saved:");
  console.log(localStorage);
  localStorage.removeItem("somekey");  //<--- key deleted here
  console.log("key deleted:");
  console.log(localStorage);
  console.log("DONE ===");
} else {
  console.log("Sorry! No web storage support..");
}

Funcionou para mim como esperado (eu uso o Google Chrome). Adaptado de: http://www.w3schools.com/html/html5_webstorage.asp .


3

Eu não acho que a solução apresentada aqui seja 100% correta, porque o evento window.onbeforeunload é chamado não apenas quando o navegador / guia está fechado (O QUE É NECESSÁRIO), mas também em todos os outros eventos. (QUE PODE NÃO SER NECESSÁRIO)

Consulte este link para obter mais informações sobre a lista de eventos que podem disparar window.onbeforeunload: -

http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx


Você pode estar certo, mas ainda assim o que você postou é um comentário, não uma resposta.
Nnnnnn 12/10


3

Depois de analisar esta questão seis anos depois de ter sido feita, descobri que ainda não há resposta suficiente para essa pergunta; que deve atingir todos os seguintes itens:

  • Limpar armazenamento local após fechar o navegador (ou todas as guias do domínio)
  • Preservar armazenamento local nas guias, se pelo menos uma guia permanecer ativa
  • Preservar armazenamento local ao recarregar uma única guia

Execute este javascript no início de cada carregamento da página para alcançar o seguinte:

((nm,tm) => {
    const
            l = localStorage,
            s = sessionStorage,
            tabid = s.getItem(tm) || (newid => s.setItem(tm, newid) || newid)((Math.random() * 1e8).toFixed()),
            update = set => {
                let cur = JSON.parse(l.getItem(nm) || '{}');
                if (set && typeof cur[tabid] == 'undefined' && !Object.values(cur).reduce((a, b) => a + b, 0)) {
                    l.clear();
                    cur = {};
                }
                cur[tabid] = set;
                l.setItem(nm, JSON.stringify(cur));
            };
    update(1);
    window.onbeforeunload = () => update(0);
})('tabs','tabid');

Edit: A idéia básica aqui é a seguinte:

  1. Ao iniciar do zero, o armazenamento da sessão recebe um ID aleatório em uma chave chamada tabid
  2. O armazenamento local é então definido com uma chave chamada tabscontendo um objeto que essas chavestabid é definida como 1.
  3. Quando a guia é descarregada, o armazenamento local tabsé atualizado para um objeto que contémtabid definido como 0.
  4. Se a guia for recarregada, ela é descarregada primeiro e retomada. Como a chave de armazenamento da sessão tabidexiste, a tabschave de armazenamento local também possui uma subchave detabid do armazenamento local também não é limpa.
  5. Quando o navegador é descarregado, todo o armazenamento da sessão será limpo. Ao retomar a sessão, o armazenamento tabidnão existe mais e um novo tabidserá gerado. Como o armazenamento local não possui uma subchave para isso tabid, nem qualquer outrotabid (todas as sessões foram fechadas), é limpo.
  6. Em uma nova guia criada, uma nova tabidé gerada no armazenamento da sessão, mas como existe pelo menos um tabs[ tabid], o armazenamento local não é limpo

11
Se o navegador travar, no entanto, window.onbeforeunloadnão será chamado e o local tabs[tabid]não será definido como 0 => o armazenamento local nunca será mais limpo. Eu acho que um cão de guarda seria mais apropriado nesse caso, em vez de escrever 1 no carregamento da guia, você deve escrever o carimbo de data / hora atual. Em seguida, na parte de redução, você deve declarar o atraso, pois esse carimbo de data / hora não é muito grande ou substituir por 0, se for. Dessa forma, você não depende da chamada real de onbeforeunload. A guia só precisa redefinir o watchdog de tempos em tempos para manter a existência de armazenamento local.
precisa saber é

1

Esta é uma pergunta antiga, mas parece que nenhuma das respostas acima é perfeita.

Caso deseje armazenar autenticação ou qualquer informação confidencial que seja destruída apenas quando o navegador estiver fechado, você poderá confiar sessionStorageelocalStorage passagem de mensagens entre guias para isso.

Basicamente, a ideia é:

  1. Você inicializar a partir de qualquer guia anterior abriu, assim, tanto o seu localStoragee sessionStorageestão vazias (se não, você pode limpar a localStorage). Você precisará registrar um ouvinte de evento de mensagem nolocalStorage .
  2. O usuário autentica / cria uma informação confidencial nesta guia (ou em qualquer outra guia aberta no seu domínio).
  3. Você atualiza o sessionStoragearquivo para armazenar as informações confidenciais e usa-o localStoragepara armazenar essas informações e, em seguida, exclui-as (você não se importa com o tempo aqui, pois o evento estava na fila quando os dados foram alterados). Qualquer outra guia aberta naquele momento será chamada de volta no evento da mensagem e atualizará seussessionStorage com as informações confidenciais.
  4. Se o usuário abrir uma nova guia no seu domínio, ela sessionStorageficará vazia. O código terá que definir uma chave no localStorage(por exemplo:) req. Qualquer outra guia (todas) será chamada de volta no evento de mensagem, veja essa chave e poderá responder com as informações sigilosas sessionStorage(como em 3), se houver.

Observe que esse esquema não depende de window.onbeforeunloadeventos frágeis (já que o navegador pode ser fechado / travado sem que esses eventos sejam acionados). Além disso, o tempo em que as informações confidenciais são armazenadas nolocalStorage é muito pequeno (já que você depende da detecção de alterações transcendentes para o evento de mensagem entre guias), portanto, é improvável que essas informações sensíveis vazem no disco rígido do usuário.

Aqui está uma demonstração desse conceito: http://jsfiddle.net/oypdwxz7/2/


Obrigado pela edição xryl669, você fez um bom argumento. Quando agora estou pensando sobre isso, seria melhor usar um trabalhador da Web compartilhado? developer.mozilla.org/en-US/docs/Web/API/SharedWorker em caso de suporte do navegador atual não é um problema
Hacktisch

Sim, você pode usar um SharedWorker ou um BroadcastChannel (ou um localStorage como este), embora os dois primeiros não estejam disponíveis no Edge. Basicamente, qualquer método que seja tabulação cruzada, janela cruzada funcionaria. A dificuldade é encontrar um que funcione em qualquer lugar com o mínimo de problemas.
precisa saber é o seguinte

1

Não existe uma maneira de detectar o fechamento do navegador; portanto, provavelmente você não pode excluir o localStorage no fechamento do navegador, mas há outra maneira de lidar com as coisas que você pode usar com o sessionCookies, pois ele destruirá após o fechamento do navegador. Isso foi implementado no meu projeto.


1

Você pode simplesmente usar o sessionStorage. Como o sessionStorage permite limpar todos os valores-chave quando a janela do navegador for fechada.

Veja lá: SessionStorage- MDN


-5

você pode tentar o seguinte código para excluir o armazenamento local:

delete localStorage.myPageDataArr;

29
Esta não é a maneira correta de excluir uma chave localStorage. Você deve usar localStorage.removeItem(key);para excluir uma chave.
MT.

11
Deve usar localStorage.removeItem (key); não a palavra-chave delete.
Rob Evans

@MT. Por que não usar delete? Eu tentei, e funciona. Existe algum efeito colateral ou algo que não devemos usar excluir? Obrigado.
user1995781

2
@ user1995781 usando deletenão é a melhor prática emlocalStorage
justmyfreak

11
@justmyfreak Isso não é uma resposta
alvitawa
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.