Identificazione tra Aggiorna e Chiudi Azioni del browser

Quando aggiorniamo la pagina (F5 o icona nel browser), per prima cosa triggers l’evento ONUNLOAD. Quando chiudiamo il browser (X nell’icona in alto a destra), si attiverà l’evento ONUNLOAD. Ora, quando viene triggersto l’evento ONUNLOAD, non c’è modo di distinguere tra aggiornare la pagina o chiudere il browser. Se hai qualche soluzione allora dammi.

C’è una soluzione.

Volevo disconnettere l’utente sul server quando la scheda o la finestra del browser era chiusa, ma non quando la pagina è stata ricaricata (potresti voler differenziare gli eventi di ricarica / chiusura per uno scopo diverso ma potresti beneficiare della mia soluzione). Ho finito con il seguente processo, basato sulla memoria locale di HTML5 e sulla comunicazione AJAX client / server:

  1. sulla tua pagina, aggiungi un onunload alla window al seguente gestore (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 } 
  2. sulla tua pagina, aggiungi un onload sul body al seguente gestore (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) } } } 
  3. sul server, raccogliere le richieste di disconnessione in un elenco e impostare un thread del timer che ispeziona l’elenco a intervalli regolari (l’ho utilizzato ogni 20 secondi). Una volta scaduto il timeout della richiesta di disconnessione (ovvero i 5 secondi mancanti), disconnettere l’utente dal server. Se nel frattempo viene ricevuta una richiesta di disconnessione, la richiesta di disconnessione corrispondente viene rimossa dall’elenco, in modo tale che l’utente non venga disconnesso.

Questo approccio è applicabile anche se si desidera distinguere tra evento chiusura scheda / finestra e link seguiti o modulo inviato. Hai solo bisogno di mettere i due gestori di eventi su ogni pagina che contiene link e moduli e su ogni pagina di destinazione link / form.

Si noti che utilizzo l’evento di beforeUnload anziché l’evento beforeUnload per gestire correttamente i collegamenti agli allegati: quando un utente fa clic su un collegamento a un allegato (ad esempio file PDF), viene inviato l’evento beforeUnload , quindi viene visualizzato un popup di apertura / salvataggio sollevato, e nient’altro (il browser non cambia la pagina visualizzata e non invia l’evento di unload ). Se stavo usando l’evento beforeUnload (come ho fatto prima), avrei rilevato un cambio di pagina quando non ce n’è.

Questo approccio è limitato ai browser che supportano l’archiviazione locale HTML5, quindi probabilmente utilizzeresti approcci specifici per browser vecchi come MSIE7.

Altri approcci basati su event.clientY non sono affidabili perché questo valore è negativo quando si fa clic sui pulsanti di ricarica o tab / chiusura finestra e positivo quando si usano le scorciatoie da tastiera per ricaricare (es. F5, Ctrl-R, …) e chiusura della finestra (ad es. Alt-F4). Affidarsi alla posizione dell’evento X non è affidabile, in quanto i pulsanti non sono posizionati nella stessa posizione su tutti i browser (ad es. Pulsante di chiusura a sinistra).

Sfortunatamente ispezionare il valore clientY / pageY dell’evento, come suggerito da alcune delle risposte qui, non è un modo affidabile per determinare se l’evento di unload viene generato da una conseguenza della chiusura della pagina da parte dell’utente.

Il motivo clientY / pageY è negativo quando si fa clic sul pulsante di chiusura del browser è perché il pulsante di chiusura è posizionato sopra la parte superiore del documento (cioè sopra il pixel 0), ma lo è anche il pulsante di ricarica che significa che facendo clic sul pulsante ricarica anche un valore negativo per clientY / pageY .

Andare lungo il percorso di controllo della coordinata x dell’evento è anche problematico perché il pulsante di chiusura del browser non è sempre sul lato destro della finestra (ad esempio è a sinistra in OS X) e perché una finestra può essere chiusa chiudendo la sua scheda o tramite la tastiera.

Utilizzare l’evento window.onbeforeunload per il caso per evitare la pagina, ma includerà tag di aggiornamento o di ancoraggio …. utilizzare un flag di convalida per lo stesso, 1 esempio per il processo è il controllo URL (URL iniziale = URL corrente ) o F5 controllare utilizzando keycode per l’aggiornamento, In caso di tag di ancoraggio utilizzare il binding ()

Nota * Il codice chiave potrebbe causare problemi in caso di Chrome.

     Test Page      

Close the browser window, or navigate to StackOverflow

Ho appena provato questo e ha risolto il problema: creare un object sessionStorage che verrà distrutto quando l’utente chiude il browser. Possiamo controllare l’object sessionStorage per scoprire se l’utente ha chiuso il browser o aggiornato la pagina (l’object sessionStorage non verrà distrutto all’aggiornamento della pagina).

Oggi ho avuto lo stesso problema e ho trovato una soluzione ansible che voglio condividere con voi.

Mentre pensavo a cosa poteva aiutare a discernere tra l’aggiornamento e la chiusura, mi sono venuti in mente i biscotti. Ricordo che l’impostazione di un cookie senza una data di scadenza esplicita lo rende disponibile solo per la sessione corrente. E una sessione corrente è chiaramente valida fino alla chiusura del browser. Ciò non include la chiusura di una scheda, ma il mio problema riguardava l’autenticazione dell’utente e non volevo disconnettere l’utente solo per aver chiuso una scheda (penso che sia lo stesso approccio del cookie ASPXAUTH di ASP.NET).

Quindi, ho inserito un semplice cookie nella raccolta document.cookies quando l’utente ha effettuato l’accesso e l’ha verificato al caricamento della pagina: se il cookie era ancora presente era un aggiornamento o una scheda riaperta e i dati dell’utente sono stati conservati, se il cookie non era presente scaduto in modo che i dati utente siano stati cancellati (come in un logout esplicito).

Spero che questo approccio possa essere utile a qualcun altro!

È una soluzione funzionante

 export class BootstrapComponent implements OnInit { validNavigation = 0; constructor( private auth: AuthenticationService ) { } ngOnInit() { const self = this; self.registerDOMEvents(); } registerDOMEvents() { const self = this; window.addEventListener('unload', () => { if (self.validNavigation === 0) { self.endSession(); } }); document.addEventListener('keydown', (e) => { const key = e.which || e.keyCode; if (key === 116) { self.validNavigation = 1; } }); } endSession() { const self = this; self.auth.clearStorage(); } } 
  $(window).bind('unload', function () { if (/Firefox[\/\s](\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 4) { console.log('firefox delete'); var data = { async: false }; endSession(data); return null; } else { console.log('NON-firefox delete'); var data = { async: true }; endSession(data); return null; } }); function endSession(data) { var id = 0 if (window) { // closeed id=1 } $.ajax({ url: '/api/commonAPI/'+id+'?Action=ForceEndSession', type: "get", data: {}, async: data.async, success: function () { console.log('Forced End Session'); } }); } 

Utilizzare if (finestra) per determinare se chiuso o semplicemente ricaricato. lavorando per me.

La mia precedente soluzione ha funzionato per me in IE. window.event sarebbe indefinito per i browser diversi da IE poiché ‘evento’ è definito globalmente in IE a differenza di altri browser. Dovresti fornire un evento come parametro in caso di altri browser. Anche che clientX non è definito per firefox, dovremmo usare pageX.

Prova qualcosa come questo …. dovrebbe funzionare per IE e Firefox questo …