Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing web browser from closing until AJAX response is returned [duplicate]

I've got a game that runs in the web browser (as a plugin) and what I'm trying to do is:

  1. Detect if the user has decided to close the browser (Alt+F4, hitting the 'X' button etc)

  2. Prevent the browser from closing whilst we fire a call to our web services to log that the user has closed the browser

  3. Once we receive the response from the web services, release the lock and allow the browser to close as requested.

The main reason we want to do this is we're having some concurrency problems and going through our logs we want to isolate people logging out / closing the browser from genuine instances where the plugin has crashed.

I looked into doing this with JQuery (for X-Browser compatability - Opera won't work but we don't have any users on Opera anyway thankfully):

$(window).bind('beforeunload', function(e) {
    e.preventDefault();
    // make AJAX call
});

The problem is that this displays a confirmation dialog to the user ('Are you sure you want to leave this page') which the user might confirm before the AJAX call is sent.

So the question is, is there a way of preventing the browser from closing until the response is received? Also 'beforeunload' fires when the page is changed as well - is there a way of distinguishing clicking on a link from actually clicking close?

Grateful for any help wrt to this!

like image 226
csdev86 Avatar asked Jan 05 '12 13:01

csdev86


1 Answers

Its tricky business to avoid the browser window from beeing closed. Actually, there is no way to do that, beside returning a non-undefined value from the onbeforeunload event, like you described.

There is one possible suggestion I can make, that is creating a synchronized ajax request within the onbeforeunload event. For instance

window.onbeforeunload = function() {
    $.ajax({
        url: '/foo',
        type: 'GET',
        async: false,
        timeout: 4000
    });
};

In theory, this will block the browser for a maximum of 4 seconds. In reality, browsers will treat this differently. For instance, Firefox (I tested it on 9), will indeed not close the window immediately, but it also does not respect the timeout value there. I guess there is an internal maximum of like 2 seconds before the request is canceled and the window/tab gets closed. However, that should be enough in most cases I guess.

Your other question (how to distinguish between clicking a link), is fairly simple. As described above, onbeforeunload looks what is getting returned from its event handlers. So lets assume we have a variable which is global for our application, we could do something like

var globalIndicator = true;

// ... lots of code

window.onbeforeunload = function() {
    return globalIndicator;
};

At this point, we would always receive a confirmation dialog when the window/tab is about to get closed. If we want to avoid that for any anchor-click, we could patch it like

$( 'a[href^=http]' ).on('click', function() {
    globalIndicator = undefined;
});
like image 197
jAndy Avatar answered Oct 13 '22 13:10

jAndy