How to handle browser close (unload event)
This article explores how to handle browser close events, providing examples and a structured overview of the relevant events.
Beforeunload & Unload Events
When a browser is closed, two events are triggered: beforeunload and unload. Let’s examine each of these events in detail.
beforeunload
The beforeunload event is fired before the document unloads. At this point, the document is still visible and the event can be cancelled.
When this event occurs, a confirmation event is triggered, allowing you to either proceed with the unload or cancel it.
Note that to trigger the confirmation event, you must implement preventDefault() or return false.
unload
The unload event fires after the beforeunload event. It is generally triggered when the document is being unloaded. Key characteristics include:
- All resources still exist.
- Resources exist but are no longer visible to the user.
- UI events (e.g.,
open,alert,confirm) do not function. - The
unloadevent cannot be cancelled under any circumstances.
Angular Example
In Angular, you can handle these events using the @HostListener decorator.
beforeunload
Handling in a Separate Function
@HostListener('window:beforeunload', ['$event'])
beforeunload(e: any) {
return false;
}
Handling in OnDestroy
@HostListener('window:beforeunload')
ngOnDestroy() {
console.log('destroy');
return false;
}
Avoiding the unload Event
It is generally recommended to avoid using the unload event due to the following reasons:
- On mobile, if a user switches to another app and then closes the browser through the app manager, the
unloadevent may not be triggered. - The
bfcacheis not triggered after anunloadevent. - Some pages with
unloadevents will not havebfcacheapplied, resulting in poor performance. - Some browsers disable the
unloadevent due tobfcacheissues.
Why Alert, Confirm Are Not Working?
According to HTML specifications, window.alert, window.confirm, and window.prompt events are ignored within unload handlers.
Furthermore, most modern browsers have enhanced security measures in place, and you can no longer customize the browser’s confirmation message.
Why Events Might Not Fire
The beforeunload or unload events should be triggered under the following circumstances:
- Closing the browser
- Closing the tab
- Refreshing the tab (using F5, the browser’s refresh button, or script-initiated refresh)
- Navigating back or forward (using the browser’s buttons or script-initiated navigation)
However, you might find that these events do not always work as expected during implementation and testing.
This is because modern browsers will immediately close a tab or browser without firing the beforeunload or unload events if there has been no user activity on the page.
Therefore, to ensure these events are triggered, users must interact with the page (even just dragging the screen) before closing it.
Alternative Events
visibilitychange
The visibilitychange event detects and reports all changes in the browser’s visibility state.
However, it can only detect minimization (i.e., hidden) and visibility changes. It cannot detect when the browser is closed. Therefore, this event is not suitable as a direct replacement for unload.
@HostListener('document:visibilitychange', ['$event'])
visibilitychanges() {
console.log(document.visibilityState);
return false;
}
pagehide
The pagehide event is a recommended alternative to the unload event.
The primary reason for this recommendation is the behavior of the bfcache. Using pagehide does not affect bfcache and, therefore, does not negatively impact page performance.
Many developers recommend this event as an alternative. The pageshow event is the recommended alternative to the load event.
Note that this event, as an alternative to unload, cannot be cancelled.
@HostListener('window:pagehide', ['$event'])
pageHide(e: any) {
e.preventDefault();
}
Using beforeunload and pagehide Together
Typically, when the beforeunload event is triggered, the pagehide event is not.
However, during a refresh, the pagehide event is triggered after the beforeunload event (similar to how the unload event behaves).
Therefore, you can use these events together if you have logic that should only be executed during a refresh.
@HostListener('window:pagehide', ['$event'])
pageHide(e: any) {
console.log('pagehide');
}
@HostListener('window:beforeunload', ['$event'])
beforeunload(e: any) {
console.log('beforeunload')
return false;
}
댓글남기기