0

I have a scenario where I need to make a cross-domain request upon leaving a page. The endpoint has all the proper CORS headers configured.

This is the request:

$.ajax({
    type: "POST",
    url: URL,
    data: {
        // some stuff
    },
    async: false
});

When tested as-is, it works great. When I try to trigger this request from an unload handler:

$(window).unload(function() {
    // same as above
});

it intermittently fails. On the occasion that it fails, I get this stack trace:

Error: A network error occurred.
    at Object.x.ajaxTransport.x.support.cors.e.crossDomain.send (http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js:6:9344)
    at Function.x.extend.ajax (http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js:6:4804)
    at http://my.web.site.com/main.js:129:11
    at x.event.dispatch (http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js:5:10006)
    at x.event.add.y.handle (http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js:5:6789)

With a jQuery DOMException and error code 19.

What's going on here? It looks like there's some race condition here that I'm unaware of, but other than setting the request to be synchronous, I'm not sure what else I can do.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Yuval Adam
  • 161,610
  • 92
  • 305
  • 395

2 Answers2

1

You simply can't rely on unload handlers. May it be jQuery's implementation or the native onbeforeunload. (Maybe onbeforeunload will work better then jQuery's implementation)
There are so many ways a user can leave the page (crash, ALT+F4, close tab, ...).

Most browsers just don't wait long enough, so your async requests will fail in most cases.

You should probably reconsider your design.

tobi.at
  • 1,267
  • 13
  • 18
  • This is not some weird crash or edge case, this is just me doing simple testing. If you know of any specific reason why browsers *will* kill pending `unload` handlers, please add some citation. – Yuval Adam Dec 05 '13 at 10:33
  • I switched to binding the `beforeunload` event and things seems to behave more consistently now. – Yuval Adam Dec 05 '13 at 10:45
  • That's great. Nonetheless you shouldn't rely on this, but I guess you already knew that ;-) – tobi.at Dec 05 '13 at 10:56
  • Why not? Test it even here on Stack Overflow. Start typing an answer => try to leave the page => prompt pops up => until you make a choice the page stays loaded. – Yuval Adam Dec 05 '13 at 11:05
  • Yes, but as I said, there a lot of ways to leave a page. – tobi.at Dec 05 '13 at 11:19
0

I ended up using the beforeunload event instead:

$(window).on('beforeunload' function() {
    // same code
});

which works just fine on all modern browsers. The beforeunload event behavior is consistent, and as long as the request is sent out synchronously, the event execution - and thus the window unloading - is paused.

This is the exact event services such as Gmail, Facebook and even Stack Overflow use to confirm is user is genuinely interested in leaving a page while in the middle of an action.

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395