First of all you should never rely on setTimeout()
for displaying the time as it is not accurate. They run in a single thread with other operations and they would deviate a lot if other operations take time to complete.
While I am writing this answer, there are already a few good answers posted by different helpful members, but they are just simply link only answers.
One of the common solution is using the help of backend technologies, but apart from the obvious, if you are going to be only relying with the javascript solution, then you will need to write the timestamp to some sort of browser storage or cookies. Then calculate the difference between current time and the initial timestamp to show the session timer.
NOTE: Following example will only work in a hosted environment since it depends on same origin policy. Executing in a developer console won't work.
var startTime;
if (sessionStorage) {
// Ask other tabs for session storage
localStorage["getTmestamp"] = "get";
window.addEventListener("storage", (event) => {
if (event.key == "getTmestamp") {
// Some tab asked for the sessionStorage -> send it
localStorage["timestamp"] = sessionStorage["timestamp"];
localStorage.removeItem("getTmestamp");
} else if (event.key == "timestamp" && !sessionStorage["timestamp"]) {
sessionStorage["timestamp"] = new Date(localStorage["timestamp"]);
localStorage.removeItem("timestamp");
}
});
} else {
console.warn("Browser doesn't support sessionStorage");
}
var interval = setInterval(() => {
if (!startTime && sessionStorage && !sessionStorage["timestamp"]) {
sessionStorage["timestamp"] = new Date();
}
startTime = new Date(sessionStorage["timestamp"]);
var currentTime = new Date();
var timeElapsed = Math.ceil((currentTime - startTime) / 1000);
var remainingTime = 30 - timeElapsed;
if (remainingTime <= 0) {
console.log("Timeout");
clearInterval(interval);
}
console.log("Session Time in seconds:", timeElapsed);
console.log("Remaining Session Time in seconds:", remainingTime);
}, 500);