Identificar entre acciones de actualización y cierre del navegador
Cuando actualizamos la página (F5 o icono en el navegador), primero se activará el evento ONUNLOAD. Cuando cerramos el navegador (X en el icono superior derecho), se activará el evento ONUNLOAD. Ahora, cuando se activa el evento ONUNLOAD, no hay forma de distinguir entre actualizar la página o cerrar el navegador. Si tienes alguna solución entonces dímelo.
Hay una solucion.
Quería desconectar al usuario en el servidor cuando se cerraba la pestaña o la ventana del navegador, pero no cuando se recargaba la página (es posible que desee diferenciar los eventos de recarga/cierre para un propósito diferente, pero puede beneficiarse de mi solución). Terminé con el siguiente proceso, basado en el almacenamiento local de HTML5 y la comunicación AJAX cliente/servidor:
en su página, agregue un
onunload
alwindow
siguiente controlador (pseudo-javascript):function myUnload(event) { if (window.localStorage) { // flag the page as being unloading window.localStorage['myUnloadEventFlag']=new Date().getTime(); } // notify the server that we want to disconnect the user in a few seconds (I used 5 seconds) askServerToDisconnectUserInAFewSeconds(); // synchronous AJAX call }
en su página, agregue un
onload
albody
siguiente controlador (pseudo-javascript):function myLoad(event) { if (window.localStorage) { var t0 = Number(window.localStorage['myUnloadEventFlag']); if (isNaN(t0)) t0=0; var t1=new Date().getTime(); var duration=t1-t0; if (duration<10*1000) { // less than 10 seconds since the previous Unload event => it's a browser reload (so cancel the disconnection request) askServerToCancelDisconnectionRequest(); // asynchronous AJAX call } else { // last unload event was for a tab/window close => do whatever you want (I do nothing here) } } }
en el servidor, recopile las solicitudes de desconexión en una lista y configure un hilo de temporizador que inspeccione la lista a intervalos regulares (yo usé cada 20 segundos). Una vez que se agota el tiempo de espera de la solicitud de desconexión (es decir, pasan los 5 segundos), desconecte al usuario del servidor. Si mientras tanto se recibe una cancelación de solicitud de desconexión, la solicitud de desconexión correspondiente se elimina de la lista, de modo que el usuario no será desconectado.
Este enfoque también es aplicable si desea diferenciar entre el evento de cierre de pestaña/ventana y los enlaces seguidos o el formulario enviado. Solo necesita colocar los dos controladores de eventos en cada página que contenga enlaces y formularios y en cada página de inicio de enlace/formulario.
Tenga en cuenta que uso el unload
evento en lugar del beforeUnload
evento para administrar correctamente los enlaces a los archivos adjuntos: cuando un usuario hace clic en un enlace a un archivo adjunto (por ejemplo, un archivo PDF), beforeUnload
se envía el evento, luego se genera una ventana emergente para abrir/guardar y nada más (el navegador no cambia la página mostrada y no envía el unload
evento). Si estuviera usando el beforeUnload
evento (como lo hice antes), habría detectado un cambio de página cuando no hay ninguno.
Este enfoque se limita a los navegadores que admiten almacenamiento local HTML5, por lo que probablemente utilizaría enfoques específicos para navegadores antiguos como MSIE7.
Otros enfoques basados en event.clientY
no son confiables porque este valor es negativo al hacer clic en los botones de recarga o cierre de pestaña/ventana, y positivo cuando se usan atajos de teclado para recargar (por ejemplo, F5, Ctrl-R, ...) y cerrar la ventana ( por ejemplo, Alt-F4). Confiar en la posición del evento X tampoco es confiable porque los botones no están ubicados en la misma posición en todos los navegadores (por ejemplo, el botón de cerrar a la izquierda).
Tal vez alguien todavía esté buscando una respuesta...
¡ Puedes usar SessionStorage para eso! SessionStorage no se borra cuando se recarga la página sino cuando se cierra. Básicamente, puede establecer un par clave/valor cuando se carga la página, pero antes de eso verifica si el par clave/valor existe. Si existe significa que la página fue recargada, si no, significa que el usuario abrió la página por primera vez o en una pestaña nueva.
if (sessionStorage.getItem('reloaded') != null) {
console.log('page was reloaded');
} else {
console.log('page was not reloaded');
}
sessionStorage.setItem('reloaded', 'yes');
De esta manera puede hacerlo doStuff()
con el onunload
evento (el usuario abandona la página) y otherStuff()
si el par clave/valor está configurado (el usuario recargó la página).
Desafortunadamente, inspeccionar el valor clientY
/ pageY
del evento, como lo sugieren algunas de las respuestas aquí, no es una forma confiable de determinar si el unload
evento se activa como consecuencia del cierre de la página por parte del usuario.
La razón por la que clientY
/ pageY
es negativo cuando hace clic en el botón de cerrar del navegador es porque el botón de cerrar está ubicado encima de la parte superior del documento (es decir, encima del píxel 0), pero también lo está el botón de recarga, lo que significa que hacer clic en el botón de recarga también resultará en un resultado negativo. valor por clientY
/ pageY
.
Seguir el camino de inspeccionar la coordenada x del evento también es problemático porque el botón de cerrar del navegador no siempre está en el lado derecho de la ventana (por ejemplo, está a la izquierda en OS X) y porque una ventana se puede cerrar cerrando su pestaña o mediante el teclado.
Hoy tuve el mismo problema y encontré una posible solución que quiero compartir con ustedes.
Mientras pensaba en lo que podría ayudar a discernir entre actualizar y cerrar, me vinieron a la mente las cookies. Recuerdo que configurar una cookie sin una fecha de vencimiento explícita la hace disponible solo para la sesión actual. Y una sesión actual es claramente válida hasta que se cierra el navegador. Esto no incluye cerrar una pestaña, pero mi problema era sobre la autenticación del usuario y no quería cerrar la sesión del usuario solo por haber cerrado una pestaña (creo que es el mismo enfoque que la ASPXAUTH
cookie de ASP.NET).
Entonces, puse una cookie simple en la document.cookies
colección cuando el usuario inició sesión y la verifiqué al cargar la página: si la cookie todavía estaba allí, fue una actualización o una pestaña reabierta y los datos del usuario se mantuvieron, si la cookie no estaba presente, la sesión había caducado, por lo que el usuario Se borraron los datos (igual que un cierre de sesión explícito).
¡Espero que este enfoque pueda ser útil para alguien más!