¿Cómo eliminar un elemento localStorage cuando la ventana / pestaña del navegador está cerrada?

403

Mi caso: localStorage con clave + valor que debe eliminarse cuando se cierra el navegador y no una sola pestaña.

Consulte mi código si es correcto y qué se puede mejorar:

//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;
});
Yosef
fuente
32
Si desea borrar el almacenamiento local al cerrar el navegador, cuestionaría sus razones para usarlo.
Dunhamzzz
16
Puede tener objetos de almacenamiento local y de sesión: usaría sessionStorage para los valores de sesión. Por cierto, establecer un valor en undefined no lo elimina ni lo elimina de localStorage, solo establece su valor en undefined.
Kennebec
2
@kennebec - Sin embargo, la configuración de undefinedsobrescribiría el elemento almacenado anteriormente. Pero sí, usar .removeItem()es más apropiado.
nnnnnn
2
solo use sessionStorage en lugar de localStorage
Alberto Acuña
2
Úselo localStorage.clear(); si desea borrar todo el almacenamiento.
Black Mamba

Respuestas:

802

debe hacerse así y no con el operador de eliminación:

localStorage.removeItem(key);
Yosef
fuente
1
¿Por qué no podemos usar el operador de eliminación, exactamente? De mis pruebas, parece que delete localStorage.keyfunciona tan bien como localStorage.removeItem(key). Me parece más claro usar eliminar cuando configuro mis variables como en localStorage.key = 1lugar de localStorage.setItem('key', 1).
Aust
66
Si funciona, técnicamente puedes usarlo. Pero considerando que removeItem se proporciona como una función miembro, parece lógico usarlo en lugar de encontrarse con un comportamiento potencialmente indefinido usando un operador separado.
kungphu
@kungphu tenga en cuenta que siempre se puede hacer (accidentalmente) localStorage.removeItem = null;, haciendo localStorage.removeItem(key);una idea potencialmente pobre.
skeggse
31
No veo cómo es una contingencia razonable para planificar. El hecho de que un lenguaje permita a las personas hacer cosas destructivas no significa que deba adoptar formas no estándar de usar las bibliotecas como defensa contra el mal uso del lenguaje. Si usted o sus colegas desarrolladores no entienden la diferencia entre invocación y asignación, tienen problemas mucho mayores que la mejor manera de eliminar elementos de localStorage.
kungphu
3
@skeggse esto es exactamente por qué es una mala idea escribir localStorage.key = 1en primer lugar, para evitar este tipo de accidentes
Jivan
114

Usar con windowpalabra clave global: -

 window.localStorage.removeItem('keyName');
viña
fuente
66
¿Por qué usar Window Object? Simplemente localStorage.removeItem(key)funciona bien.
Pardeep Jain
3
mira
¿Esta solución realmente funciona para IE 11? Por favor recomiende. Estoy teniendo este problema en el código angular 5.
Karan
95

Puede hacer uso del beforeunloadevento en JavaScript.

Usando JavaScript vainilla podría hacer algo como:

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

Eso eliminará la clave antes de cerrar la ventana / pestaña del navegador y le pedirá que confirme la acción de cerrar la ventana / pestaña. Espero que eso resuelva tu problema.

NOTA: El onbeforeunloadmétodo debería devolver una cadena.

MONTE.
fuente
Esto fue realmente útil. Puede ser bueno aceptar la respuesta (incluso después de todo este tiempo).
Richard Morgan
8
@dhsto VanillaJS es JavaScript simple :) Mira aquí: ¿Qué es VanillaJS? .
Bharat Khatri
1
Un problema es que esto se llama incluso si navega en la misma página, no solo cuando la pestaña está cerrada, lo que podría no ser lo que se pretende. Nota al margen: al regresar indefinido de onbeforeunload se deshabilitará el mensaje que se muestra al descargar.
Stan Bondi
¿Qué sucede si el usuario desea permanecer en la página y usted ya elimina el almacenamiento local? Además, la solución no funciona en Chrome e IE11
oracleruiz
¿Por qué no usar sessionStorage entonces?
Sachin Prasad
94

En su lugar, debe usar sessionStorage si desea que la clave se elimine cuando se cierre el navegador.

Graou13
fuente
3
Esta es la mejor respuesta; sessionStoragees el remedio para lo que describe el autor de la pregunta.
Benny
8
+1 por mencionar sessionStorage, pero el Borrador del Editor del W3C dice: "La vida útil de un contexto de navegación puede no estar relacionada con la vida útil del proceso del agente de usuario en sí mismo, ya que el agente de usuario puede admitir la reanudación de sesiones después de un reinicio".
Tamás
28
El problema con 'sessionStorage' es que no se almacena cuando abre una nueva pestaña, por ejemplo, con Ctrl haga clic en un enlace. Necesito un localStorage / sessionStorage híbrido lol.
Edwin Stoteler
3
@EdwinStoteler Yo también. Estoy un poco confundido sobre lo que estaban pensando cuando lo diseñaron de esta manera. Realmente necesito acceso esencialmente a un almacenamiento de navegador solo en memoria que se destruye cuando el navegador se cierra. Quiero almacenar información confidencial de manera que se pueda acceder a través de un dominio completo, pero no quiero que esa información golpee ningún disco duro.
BT
19

Intenta usar

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

Espero que esto funcione para usted

Rafael Marques
fuente
2
¿Desea borrar el almacenamiento local completo? si es así, solo uselocalStorage.clear();
Rafael Marques
estaba claro lo que quiero en cuestión - solo clave borrar + valor
Yosef
12
Esto limpiará todo el almacenamiento local. mala solución!
Emmy
12

Hay un caso de uso muy específico en el que cualquier sugerencia de usar sessionStorage en lugar de localStorage realmente no ayuda. El caso de uso sería algo tan simple como tener algo almacenado mientras tiene al menos una pestaña abierta, pero invalidarlo si cierra la última pestaña restante. Si necesita que sus valores se guarden en tablas y ventanas, sessionStorage no lo ayudará a menos que le complique la vida a los oyentes, como lo he intentado. Mientras tanto, localStorage sería perfecto para esto, pero hace el trabajo "demasiado bien", ya que sus datos estarán esperando allí incluso después de reiniciar el navegador. Terminé usando un código personalizado y una lógica que aprovecha ambos.

Prefiero explicar y luego dar el código. Primero almacene lo que necesita en localStorage, luego también en localStorage cree un contador que contendrá el número de pestañas que ha abierto. Esto aumentará cada vez que se cargue la página y disminuirá cada vez que la página se descargue. Puede elegir aquí los eventos que usará, sugeriría 'cargar' y 'descargar'. En el momento de la descarga, debe realizar las tareas de limpieza que le gustaría cuando el contador llegue a 0, lo que significa que está cerrando la última pestaña. Aquí viene la parte difícil: no he encontrado una forma confiable y genérica de diferenciar entre una recarga de página o navegación dentro de la página y el cierre de la pestaña. Entonces, si los datos que almacena no son algo que puede reconstruir en la carga después de verificar que esta es su primera pestaña, entonces no puede eliminarlo en cada actualización. En su lugar, debe almacenar un indicador en sessionStorage en cada carga antes de aumentar el contador de pestañas. Antes de almacenar este valor, puede hacer una verificación para ver si ya tiene un valor y si no lo tiene, esto significa que está cargando en esta sesión por primera vez, lo que significa que puede hacer la limpieza en la carga si esto el valor no está establecido y el contador es 0.

Solthun
fuente
Como respuesta a "¿por qué no se utiliza sessionStorage?" enfoque, también de w3schools.com/html/html5_webstorage.asp : "window.sessionStorage - almacena datos para una sesión (los datos se pierden cuando se cierra la pestaña)". Entonces la respuesta es solo eso. sessionStorage es inútil si quieres algo persistente incluso en el caso de uso que describí.
Solthun
3
Estoy pensando que la mejor implementación para esto sería un servicio browserWatcher que básicamente dispara eventos que otros componentes pueden escuchar (es decir, abrir navegador, cerrar navegador, cargar broswer, descargar navegador, etc.) y ocultar todos estos detalles de implementación dentro de él Cada componente puede decidir qué eventos necesita manejar para hacer su trabajo. Mi única pregunta sería qué sucede si se corta la energía de la máquina o algo así, entonces estas propiedades permanecerían en localStorage la próxima vez que se abra el navegador si no ?
pQuestions123
11

usar sessionStorage

El objeto sessionStorage es igual al objeto localStorage, excepto que almacena los datos para una sola sesión. Los datos se eliminan cuando el usuario cierra la ventana del navegador.

El siguiente ejemplo cuenta la cantidad de veces que un usuario ha hecho clic en un botón, en la sesión actual:

Ejemplo

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.";
DilanG
fuente
1
Los datos se eliminan al cerrar la pestaña del navegador.
Kosmonaft
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]);
}
Gil Snovsky
fuente
5
localStorage.removeItem(key);  //item

localStorage.clear(); //all items
William Cauich
fuente
1
Al responder una pregunta anterior, su respuesta sería mucho más útil para otros usuarios de StackOverflow si incluyera algún contexto para explicar cómo ayuda su respuesta, particularmente para una pregunta que ya tiene una respuesta aceptada. Ver: ¿Cómo escribo una buena respuesta ?
Tân
Me parece lo suficientemente claro
Giorgio Tempesta
4

Aunque algunos usuarios ya respondieron esta pregunta, estoy dando un ejemplo de configuración de la aplicación para resolver este problema.

Tuve el mismo problema Estoy usando el módulo https://github.com/grevory/angular-local-storage en mi aplicación angularjs. Si configura su aplicación de la siguiente manera, guardará la variable en el almacenamiento de la sesión en lugar del almacenamiento local. Por lo tanto, si cierra el navegador o cierra la pestaña, el almacenamiento de la sesión se eliminará automáticamente. No necesitas hacer nada.

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

Espero que ayude.

usuario1012513
fuente
4

Hay cinco métodos para elegir:

  • setItem (): agrega clave y valor a localStorage
  • getItem (): recupera un valor mediante la clave de localStorage
  • removeItem (): elimina un elemento por clave de localStorage
  • clear (): borra todo localStorage
  • key (): pasó un número para recuperar la enésima clave de un localStorage

Puede usar clear (), este método cuando se invoca borra todo el almacenamiento de todos los registros para ese dominio. No recibe ningún parámetro.

window.localStorage.clear();
marcorchito8
fuente
3

Aquí hay una prueba simple para ver si tiene soporte de navegador cuando trabaja con almacenamiento 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..");
}

Funcionó para mí como se esperaba (uso Google Chrome). Adaptado de: http://www.w3schools.com/html/html5_webstorage.asp .

rdonatoiop
fuente
3

No creo que la solución presentada aquí sea 100% correcta porque el evento window.onbeforeunload se llama no solo cuando el navegador / Tab está cerrado (LO QUE SE REQUIERE), sino también en todos los demás eventos. (QUE NO SE REQUIERE)

Consulte este enlace para obtener más información sobre la lista de eventos que pueden activar window.onbeforeunload: -

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

miztaken
fuente
Puede que tengas razón, pero lo que has publicado es un comentario, no una respuesta.
nnnnnn
3

¿Por qué no se utiliza sessionStorage?

"El objeto sessionStorage es igual al objeto localStorage, excepto que almacena los datos para una sola sesión. Los datos se eliminan cuando el usuario cierra la ventana del navegador".

http://www.w3schools.com/html/html5_webstorage.asp

wjfinder77
fuente
3

Después de mirar esta pregunta 6 años después de haberla preguntado, descubrí que todavía no hay una respuesta suficiente para esta pregunta; que debería lograr todo lo siguiente:

  • Borrar el almacenamiento local después de cerrar el navegador (o todas las pestañas del dominio)
  • Preserve el almacenamiento local en las pestañas, si al menos una pestaña permanece activa
  • Preserve el almacenamiento local al volver a cargar una sola pestaña

Ejecute esta pieza de javascript al comienzo de cada carga de página para lograr lo anterior:

((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');

Editar: La idea básica aquí es la siguiente:

  1. Al comenzar desde cero, al almacenamiento de la sesión se le asigna una identificación aleatoria en una clave llamada tabid
  2. El almacenamiento local se establece con una clave llamada que tabscontiene un objeto, esa clave tabidse establece en 1.
  3. Cuando se descarga la pestaña, el almacenamiento local tabsse actualiza a un objeto que contiene el tabidconjunto en 0.
  4. Si la pestaña se vuelve a cargar, primero se descarga y se reanuda. Dado que la clave de almacenamiento de la sesión tabidexiste, y también la tabsclave de almacenamiento local con una subclave del tabidalmacenamiento local no se borra.
  5. Cuando se descarga el navegador, se borrará todo el almacenamiento de la sesión. Al reanudar la sesión, el almacenamiento tabidya no existe y tabidse generará uno nuevo . Dado que el almacenamiento local no tiene una subclave para esto tabid, ni ninguna otra tabid(todas las sesiones se cerraron), se borra.
  6. Al crear una nueva pestaña, tabidse genera una nueva en el almacenamiento de la sesión, pero como existe al menos una tabs[ tabid], el almacenamiento local no se borra
Hacktisch
fuente
1
Sin embargo, si el navegador falla, window.onbeforeunloadno se llamará y el local tabs[tabid]no se establecerá en 0 => el almacenamiento local nunca más se borrará. Creo que un perro guardián sería más apropiado en ese caso, en lugar de escribir 1 al cargar la pestaña, debería escribir la marca de tiempo actual. Luego, en la parte de reducción, debe afirmar el retraso ya que esa marca de tiempo no es demasiado grande o reemplazarla por 0 si lo es. De esa manera, no depende de la llamada real de onbeforeunload. La pestaña solo necesita restablecer el perro guardián de vez en cuando para mantener la existencia de almacenamiento local.
xryl669
1

Esta es una vieja pregunta, pero parece que ninguna de las respuestas anteriores es perfecta.

En el caso de que desee almacenar la autenticación o cualquier información confidencial que se destruya solo cuando el navegador esté cerrado, puede confiar sessionStorageylocalStorage pasar mensajes de tabla cruzada.

Básicamente, la idea es:

  1. Usted inicia desde ninguna pestaña anterior abierta, por lo tanto, tanto su localStorage como sessionStorageestán vacías (si no, puedes borrar el localStorage). Deberá registrar un detector de eventos de mensajes en ellocalStorage .
  2. El usuario autentica / crea una información confidencial en esta pestaña (o en cualquier otra pestaña abierta en su dominio).
  3. Actualizas el sessionStorage para almacenar la información confidencial, y usa localStoragepara almacenar esta información, luego la elimina (no le importa el tiempo aquí, ya que el evento se puso en cola cuando los datos cambiaron). Cualquier otra pestaña abierta en ese momento se volverá a llamar al evento de mensaje y actualizará susessionStorage con la información confidencial.
  4. Si el usuario abre una nueva pestaña en su dominio, sessionStorageestará vacía. El código tendrá que establecer una clave en localStorage(por ejemplo:) req. Cualquier otra pestaña (todas) se volverá a llamar en el evento del mensaje, verá esa clave y podrá responder con la información confidencial de su sessionStorage(como en 3), si la tienen.

Tenga en cuenta que este esquema no depende del window.onbeforeunloadevento que es frágil (ya que el navegador puede cerrarse / bloquearse sin que se activen estos eventos). Además, el tiempo que la información confidencial se almacena en ellocalStorage es muy pequeño (ya que depende de la detección de cambios de transitorios para eventos de mensajes cruzados), por lo que es poco probable que dicha información confidencial se filtre en el disco duro del usuario.

Aquí hay una demostración de este concepto: http://jsfiddle.net/oypdwxz7/2/

xryl669
fuente
Gracias por la edición xryl669, hiciste un buen comentario. Cuando estoy pensando en esto, ¿sería mejor utilizar un trabajador web compartido? developer.mozilla.org/en-US/docs/Web/API/SharedWorker en caso de que el soporte actual del navegador no sea un problema
Hacktisch
Sí, puede usar SharedWorker o BroadcastChannel (o un LocalStorage como este), aunque los dos primeros no están disponibles en Edge. Básicamente, cualquier método que sea tabla de referencias cruzadas, ventana cruzada, funcionaría. La dificultad es encontrar uno que funcione en todas partes con el mínimo de molestias.
xryl669
1

No existe tal forma de detectar el cierre del navegador, por lo que probablemente no pueda eliminar localStorage en el cierre del navegador, pero hay otra forma de manejar las cosas que puede usar sessionCookies, ya que destruirá después del cierre del navegador. Esto lo implementé en mi proyecto.

Amit Dwivedi
fuente
1

Simplemente puede usar sessionStorage. Debido a que sessionStorage permite borrar todos los valores clave cuando se cierra la ventana del navegador.

Ver allí: SessionStorage- MDN

Moshiur Rahman
fuente
-5

Puede intentar el siguiente código para eliminar el almacenamiento local:

delete localStorage.myPageDataArr;
aztechy
fuente
29
Esta no es la forma correcta de eliminar una clave localStorage. Debe usar localStorage.removeItem(key);para eliminar una clave.
MT.
1
Debería usar localStorage.removeItem (clave); no es la palabra clave eliminar.
Rob Evans
@MONTE. ¿Por qué no usar delete? Lo intenté y funciona. ¿Hay algún efecto secundario o algo que no debamos usar para eliminar? Gracias.
user1995781
2
@ user1995781 usar deleteno es la mejor práctica enlocalStorage
justmyfreak
1
@justmyfreak Eso no es una respuesta
alvitawa