I made a clock. I realized that when I switch another tab and came back after a while the clock stop behind current time. I found something named web workers, is it related to this??
Same senteces, don’t read. I made a clock. I realized that when I switch another tab and came back after a while the clock stop behind current time. I found something named web workers, is it related to this??
I expected the code work anytime but it didn’t.
The code:
let numbers = document.getElementsByClassName('number');
let numbersLength = numbers.length-1;
let numberContainer = document.querySelectorAll('.number > div');
let minute = document.querySelector('#minute');
let hour = document.querySelector('#hour');
let second = document.querySelector('#second');
let startSecond = new Date().getSeconds()*6;
let startHour = new Date().getHours()*30;
let startMinute = new Date().getMinutes()*6;
setInterval(increaseSecond, 1000);
function readyHour() {
//second starting position
second.style.transform = `rotate(${startSecond}deg)`;
minute.style.transform = `rotate(${startMinute}deg)`;
hour.style.transform = `rotate(${startHour}deg)`;
//numbers positions
for(let i = 0; i <= numbersLength; i++){
numbers[i].style.transform = `rotate(${i*30}deg)`;
numberContainer[i].style.transform = `rotate(${-(i*30)}deg)`;
}
}
readyHour();
function increaseSecond(){
let currentSecond = new Date().getSeconds();
let currentMinute = new Date().getMinutes();
let currentHour = new Date().getHours();
second.style.transform = `rotate(${currentSecond*6}deg)`;
if(currentSecond === 0){
minute.style.transform = `rotate(${currentMinute*6}deg)`;
};
if(currentMinute === 0)
hour.style.transform = `rotate(${currentHour*30}deg)`;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.clock{
background-color: black;
height: 350px;
width: 350px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
position: relative;
border: 8px solid #31e1e7;
}
.number{
font-size: 3rem;
color: #ffffff;
text-align: center;
position: absolute;
height: 100%;
width: 100%;
}
.hand{
position: absolute;
left: 49.2%;
bottom: 50%;
width: 3px;
background-color: red;
transform-origin: bottom;
}
#second{
z-index: 10;
height: 120px;
}
#minute{
height: 110px;
}
#hour{
height: 65px;
}
#clock-center{
background-color: #ffffff;
height: 15px;
width: 15px;
z-index: 11;
border-radius: 50%;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="assets/main.css">
</head>
<body>
</head>
<body>
<div class="clock">
<div id="clock-center"></div>
<div class="hand " id="minute"></div>
<div class="hand " id="hour"></div>
<div class="hand" id="second"></div>
<div class="number"><div>12</div></div>
<div class="number"><div>1</div></div>
<div class="number"><div>2</div></div>
<div class="number"><div>3</div></div>
<div class="number"><div>4</div></div>
<div class="number"><div>5</div></div>
<div class="number"><div>6</div></div>
<div class="number"><div>7</div></div>
<div class="number"><div>8</div></div>
<div class="number"><div>9</div></div>
<div class="number"><div>10</div></div>
<div class="number"><div>11</div></div>
</div>
<script src="assets/main.js"></script>
</body>
</html>
2
Answers
Browsers often optimize background tabs to use fewer resources, which can include throttling or stopping JavaScript execution. In your case, using a Web Worker can indeed solve this problem. A Web Worker runs in the background independently of the main JavaScript thread and continues executing even if the tab is not active.
Here’s how you can implement your clock using a Web Worker:
worker.js (The Web Worker script)
main.js
In this setup:
Using a Web Worker ensures that your clock continues to run even if the tab is not active. Remember to adjust the paths to your worker script and include the appropriate HTML structure for your clock elements.
The problem you face is not so much related to the inactivity of the browser page and that timer ticks are suspended. Once the page comes into view again, these ticks resume immediately, so there should be opportunity for your code to display the clock correctly on those ticks.
The problem is really caused by the fact that your code only updates the minute hand when a minute has passed, and the hour hand only updates when an hour has passed. This practically means that when you come back to the page after a long period of activity, the minute and hour hand will not be updated until enough time has passed, and will appear wrong during that time.
The solution is simple: always update the display of all three hands, unconditionally, at every tick of
setInterval
.So change this:
to this:
This will fix the issue.
More remarks
I find it not intuitive that the hour hand moves with steps of 30 degrees. That means that when it is one minute to 12, the hour hand still points to 11, giving the false impression it is one minute to 11.
To a lesser extent this also applies to the minute hand: it could move with smaller steps than 6 degrees giving a more fluent display.
Here is how I would change it: