I'm currently in the process of developing a multiplayer game app using vue.js. For state management, I've opted to utilize vuex and for the backend server, I have integrated Firestore.
A crucial aspect of the app is handling user interactions when they leave the platform. Specifically, if a user closes the browser tab or navigates away from the page, the game data stored in Firestore needs to be deleted. However, if the user simply refreshes the page, the Firestore files should remain intact to facilitate a seamless reload process.
Therefore, there is a need to distinguish between a page refresh and other forms of exiting the app.
In the code snippet below, you can observe that during vue's created lifecycle, I establish a "beforeunload" event listener and initialize my Firestore listeners:
created() {
// This window event listener fires when the user
// navigates away from or closes the browser window
window.addEventListener("beforeunload", (event) => {
const isByRefresh = getUnloadInitiator();
if (!isByRefresh) {
this.stopFirestoreListeners("beforeunload");
}
// Cancel the event. This allows the user to cancel via popup. (for debug purposes)
event.preventDefault();
event.returnValue = "";
// the absence of a returnValue property on the event
// guarantees the browser unload happens
// delete event["returnValue"];
});
this.startFirestoreListeners("created");
},
Highlighted below is the getUnloadInitiator function that requires assistance. Currently, the function mainly logs various performance values:
function getUnloadInitiator() {
// check for feature support before continuing
if (performance.mark === undefined) {
console.log("performance.mark NOT supported");
return false;
}
console.log("===============================");
// Yes I know that performance.navigation is depreciated.
const nav = performance.navigation;
console.log("nav=", nav);
console.log("===============================");
// Use getEntriesByType() to just get the "navigation" events
var perfEntries = performance.getEntriesByType("navigation");
for (var i = 0; i < perfEntries.length; i++) {
var p = perfEntries[i];
console.log("= Navigation entry[" + i + "]=", p);
// other properties
console.log("type = " + p.type);
}
console.log("===============================");
performance.mark("beginLoop");
const entries = performance.getEntries({
name: "beginLoop",
entryType: "mark",
});
const firstEntry = entries[0];
console.log("firstEntry.type=", firstEntry.type);
console.log("===============================");
//TODO: Determine how unload was initiated
return true;
}
The following output displays the results from the console.logs. Surprisingly, all scenarios—refreshing the page, closing the browser tab, or navigating away—show "reload" as the navigation type:
===============================
nav= PerformanceNavigation {type: 1, redirectCount: 0}
===============================
= Navigation entry[0]= PerformanceNavigationTiming {unloadEventStart: 25.399999976158142, unloadEventEnd: 25.69999998807907, domInteractive: 633, domContentLoadedEventStart: 633, domContentLoadedEventEnd: 633, ...}
type = reload
===============================
firstEntry.type= reload
===============================
If anyone could provide insights on differentiating between these actions (refreshing, closing tab, or navigating away), it would be greatly appreciated. The ability to determine such distinctions is evident through the debug pop-up used for canceling browser operations.
Thank you!