Skip to content

Commit db6d098

Browse files
committed
Add sendBeacon verification and fetch keepalive fallback
Log disconnect method used and fallback to fetch with keepalive if sendBeacon fails during pagehide. Addresses #285
1 parent a4911ab commit db6d098

File tree

1 file changed

+55
-2
lines changed

1 file changed

+55
-2
lines changed

modules/javascript/src/main/webapp/javascript/atmosphere.js

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@
5151
*/
5252
var _beforeUnloadState = false;
5353

54+
/**
55+
* {boolean} If page is being hidden/unloaded (pagehide event).
56+
* Used to ensure reliable disconnect methods are used.
57+
*
58+
* @private
59+
*/
60+
var _pageHideState = false;
61+
5462
var atmosphere = {
5563
version: "4.0.2",
5664
onError: function (response) {
@@ -2653,10 +2661,53 @@
26532661
rq.force = true;
26542662
rq.suspend = false;
26552663
rq.timeout = 1000;
2664+
2665+
// Use reliable methods during page unload
26562666
if (_request.unloadBackwardCompat) {
2667+
atmosphere.util.debug("Using XHR for disconnect (backward compat)");
26572668
_executeRequest(rq);
2669+
} else if (navigator.sendBeacon) {
2670+
atmosphere.util.debug("Using sendBeacon for reliable disconnect");
2671+
var sent = navigator.sendBeacon(rq.url, rq.data);
2672+
if (!sent && _pageHideState && typeof fetch === 'function') {
2673+
// Fallback to fetch with keepalive if sendBeacon fails during pagehide
2674+
atmosphere.util.debug("sendBeacon failed, falling back to fetch keepalive");
2675+
try {
2676+
fetch(rq.url, {
2677+
method: rq.method,
2678+
body: rq.data,
2679+
keepalive: true,
2680+
headers: {
2681+
'Content-Type': rq.contentType || 'text/plain'
2682+
}
2683+
}).catch(function(e) {
2684+
atmosphere.util.debug("fetch keepalive failed: " + e);
2685+
});
2686+
} catch (e) {
2687+
atmosphere.util.debug("fetch keepalive error: " + e);
2688+
}
2689+
}
2690+
} else if (_pageHideState && typeof fetch === 'function') {
2691+
// Use fetch with keepalive if sendBeacon not available during pagehide
2692+
atmosphere.util.debug("Using fetch keepalive for reliable disconnect");
2693+
try {
2694+
fetch(rq.url, {
2695+
method: rq.method,
2696+
body: rq.data,
2697+
keepalive: true,
2698+
headers: {
2699+
'Content-Type': rq.contentType || 'text/plain'
2700+
}
2701+
}).catch(function(e) {
2702+
atmosphere.util.debug("fetch keepalive failed: " + e);
2703+
});
2704+
} catch (e) {
2705+
atmosphere.util.debug("fetch keepalive error: " + e);
2706+
}
26582707
} else {
2659-
navigator.sendBeacon(rq.url, rq.data);
2708+
// Last resort fallback
2709+
atmosphere.util.debug("Using XHR for disconnect (no reliable methods available)");
2710+
_executeRequest(rq);
26602711
}
26612712
}
26622713

@@ -3469,8 +3520,10 @@
34693520
},
34703521
pageHide: function (event) {
34713522
atmosphere.util.debug(new Date() + " Atmosphere: pagehide event");
3523+
_pageHideState = true;
34723524

3473-
// Only cleanup if page is being persisted to bfcache or actually unloading
3525+
// Disconnect during pagehide to ensure proper cleanup
3526+
// Relies on sendBeacon or fetch keepalive for reliable delivery during page unload
34743527
// event.persisted indicates if page is entering bfcache
34753528
if (requests.length > 0) {
34763529
atmosphere.unsubscribe();

0 commit comments

Comments
 (0)