AJAX on web page unloading
TL;DR On page unload AJAX network requests are sent by all browsers if – contrary to the general advice – the synchronous flavour of
XMLHttpRequest (SJAX) is used.
Update (4. November 2015):
- Use the
"pagehide"event instead of the
"unload"event, since if an unload handler is present, the in-memory cache („Back-Forward-Cache“) is not enabled for the page.
- Firefox and Google Chrome implement the Beacon API especially tailored for sending data during unloading of the document. But it has issues when quitting the browser.
- Using SJAX comes with the penalty that the browser tab is blocked until the response from the remote server is received.
The Problem of sending goodbye data on page unload
occurs often that a single page web application (SPA) needs to change the state in its cloud end (clean up resources, close network connections…) when a user quits the application (i.e. she closes the browser window).
The obvious choice is to subscribe for the DOM window’s
beforeunload events with handler methods and trigger a remote signal on a server via
XMLHttpRequest (i.e. AJAX). The result of that signalling is usually of no interest to the SPA front end (browser page).
However what can be done in these handlers has always depended on the various browser implementations.
The beforeunload Event Handler
unload handler apply, except for the Chrome browser.
In the unload Event Handler
Tests (see the table below) show that many browsers do not issue network requests if done asynchronously.
is to use AJAX without the first ‚A‘ or S(ynchronous)JAX if there were such a thing. Thus simply setting the
async flag of the
XMLHttpRequest.open method to
The Beacon API did not succeed sending data while quitting the browser. Even more annoying is that navigator.sendBeacon returns true indicating that the request is scheduled. Thus it is not possible to employ a fallback method. For this case I’ve found SJAX to be more robust than the Beacon API.
The network activity was detected by running Fiddler Web Debugger and analysing the logs on PutsReq.
|AJAX (async = true)||ok||ok||fails||?|
|AJAX (async = true)|
after dismissed a beforeunload prompt
|SJAX (async = false)||ok||ok||ok||ok|
|„pagehide“ event handler|
|v.14||v.11||v.43||v.47 / v.39 on Android 5.1||v.9 / on iOS 10.2|
|page navigation||sendBeacon||AJAX||AJAX, sendBeacon||AJAX, sendBeacon||SJAX / SJAX|
|page reload||sendBeacon||AJAX||AJAX, sendBeacon||SJAX, sendBeacon||SJAX / SJAX|
|closing the tab||sendBeacon||AJAX||AJAX (FF 44) ||
SJAX (FF 43), sendBeacon
|sendBeacon||SJAX / –|
|closing the browser||sendBeacon||AJAX||–||– / n/a||– / n/a|