Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

javascript - How can I handle browser tab close event in Angular? Only close, not refresh

My goal is remove user cookies when browser tab closed.

Is it possible? Can I handle browser tab close event without refresh case?

If I use beforeunload or unload events, function triggered when user refresh page, I don't want this, I want just run when closed tab.

How can I do this in Angular?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is, tragically, not a simple problem to solve. But it can be done. The answer below is amalgamated from many different SO answers.

Simple Part: Knowning that the window is being destroyed. You can use the onunload event handle to detect this.

Tricky Part:

Detecting if it's a refresh, link follow or the desired window close event. Removing link follows and form submissions is easy enough:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
}); 

Poor-man's Solution

Checking event.clientY or event.clientX to determine what was clicked to fire the event.

function doUnload(){
 if (window.event.clientX < 0 && window.event.clientY < 0){
   alert("Window closed");
 }
 else{
   alert("Window refreshed");
 }
}

Y-Axis doesn't work cause it's negative for clicks on reload or tab/window close buttons, and positive when keyboard shortcuts are used to reload (e.g. F5, Ctrl-R, ...) and window closing (e.g. Alt-F4). X-Axis is not useful since different browsers have differing button placements. However, if you're limited, then running the event coordinates thru a series of if-elses might be your best bet. Beware that this is certainly not reliable.

Involved Solution

(Taken from Julien Kronegg) Using HTML5's local storage and client/server AJAX communication. Caveat: This approach is limited to the browsers which support HTML5 local storage.

On your page, add an onunload to the window to the following handler

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
}

Then add a onloadon the body to the following handler

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
        }
    }
} 

On the server, collect the disconnection requests in a list and set a timer thread which inspects the list at regular intervals (I used every 20 seconds). Once a disconnection request timeout (i.e. the 5 seconds are gone), disconnect the user from the server. If a disconnection request cancelation is received in the meantime, the corresponding disconnection request is removed from the list, so that the user will not be disconnected.

This approach is also applicable if you want to differentiate between tab/window close event and followed links or submitted form. You just need to put the two event handlers on every page which contains links and forms and on every link/form landing page.

Closing Comments (pun intended):

Since you want to remove cookies when the window is closed, I'm assuming it's to prevent them from being used in a future session. If that's a correct assumption, the approach described above will work well. You keep the invalidated cookie on the server (once client is disconnected), when the client creates a new session, the JS will send the cookie over by default, at which point you know it's from an older session, delete it and optionally provide a new one to be set on the client.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...