|
51 | 51 | */ |
52 | 52 | var _beforeUnloadState = false; |
53 | 53 |
|
| 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 | + |
54 | 62 | var atmosphere = { |
55 | 63 | version: "4.0.2", |
56 | 64 | onError: function (response) { |
|
2653 | 2661 | rq.force = true; |
2654 | 2662 | rq.suspend = false; |
2655 | 2663 | rq.timeout = 1000; |
| 2664 | + |
| 2665 | + // Use reliable methods during page unload |
2656 | 2666 | if (_request.unloadBackwardCompat) { |
| 2667 | + atmosphere.util.debug("Using XHR for disconnect (backward compat)"); |
2657 | 2668 | _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 | + } |
2658 | 2707 | } 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); |
2660 | 2711 | } |
2661 | 2712 | } |
2662 | 2713 |
|
|
3469 | 3520 | }, |
3470 | 3521 | pageHide: function (event) { |
3471 | 3522 | atmosphere.util.debug(new Date() + " Atmosphere: pagehide event"); |
| 3523 | + _pageHideState = true; |
3472 | 3524 |
|
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 |
3474 | 3527 | // event.persisted indicates if page is entering bfcache |
3475 | 3528 | if (requests.length > 0) { |
3476 | 3529 | atmosphere.unsubscribe(); |
|
0 commit comments