Fixing double running of javascript code in different tabs - javascript

I created a little timer which runs from 30seconds down to 0 and saved in the localStorage, butthen restarts after a event and again begins at 30secs. But if I open 2 tabs of the same page the code runs double. That means that after 1 seconds the timer jumps for example from 30 to 28.
function timer(){
localStorage.setItem("time", 30);
setInterval(function(){
localStorage.setItem("time", localStorage.getItem("time") - 1);
timerPlace.innerHTML = localStorage.getItem("time");
if(localStorage.getItem("time") < 0){
localStorage.setItem("time", 0);
timerPlace.innerHTML = "TIME TO PLACE !";
}
}, 1000);
if(localStorage.getItem("time") === null){
localStorage.setItem("time", 30);
}
}
I already thought of getting the number of opened tabs and do something with this. Or maybe there is a way to only run a javascript code in one tab.

Store the start time of your count in localStorage. Then calculate the distance from it in seconds. when reach 30, clear that value.
This example is without using localStorage because not allowed in a stack snippet.
var start = (new Date()).getTime();
var ind_id
ind_id = setInterval(function() {
var now = (new Date()).getTime()
var diff_in_seconds = Math.round((now - start) / 1000)
if (diff_in_seconds >= 30) {
cancelInterval(ind_id)
return;
}
timerPlace.innerHTML = (30 - diff_in_seconds)
}, 1000)
<div id="timerPlace"></div.>

Related

How to synchronise a timer for everyone client

I have a working timer, but it runs from 25 seg every time who the website is visited by a client, I want to synchronise it. F.E. if i visit my webpage in mY Pc, and when it show 15seg left, i visit it from other pc and i want it to show 15 left too.
function timerr(){
var initial = 25000;
var count = initial;
var counter;
var initialMillis;
function timer() {
if (count <= 0) {
clearInterval(counter);
return;
}
var current = Date.now();
count = count - (current - initialMillis);
initialMillis = current;
displayCount(count);
function displayCount(count) {
var res = count / 1000;
if (res<0.1){
document.getElementById("timer").innerHTML = "";
}
else{
tiempo = res.toPrecision(count.toString().length);
tiempo_corto = tiempo.slice(0,-1);
document.getElementById("timer").innerHTML = tiempo_corto;
}
}
clearInterval(counter);
initialMillis = Date.now();
counter = setInterval(timer, 10);
}
If you want everyone to have the same timer count down every 25 seconds and stop at the exact same time, then you can simply use timestamps to keep everything in sync. Here's an example countdown timer that'll restart every 6 seconds (from 5 to 0) and will hit zero at the exact same time for everyone (unless their computer clock is off).
const timerElement = document.getElementById('timer')
const TIMER_DURATION = 6
function step() {
const timestamp = Date.now() / 1000
const timeLeft = (TIMER_DURATION - 1) - Math.round(timestamp) % TIMER_DURATION
timerElement.innerText = timeLeft
const timeCorrection = Math.round(timestamp) - timestamp
setTimeout(step, timeCorrection*1000 + 1000)
}
step()
<p id="timer"></p> seconds
Try it - open this page up in two different tabs and run it. This is set up to automatically account for the fact that setTimeout doesn't always trigger at the delay you asked it to do so (it'll adjust the next setTimeout with a timeCorrection value to correct these issues).
The basic principle is that we're getting the current timestamp and modding it by the amount of time we want this timer to last (6 seconds in the above example). This value will always be the same for everyone, and will always be a number that ranges from 0 to 5. It will also be a number that counts up every second (which is why we then subtract (TIMER_DURATION - 1) from it, to cause the number to count down instead).

setInterval halted when I move between browser tabs in react [duplicate]

function initTimer(timeLeft) {
var Me = this,
TotalSeconds = 35,
Seconds = Math.floor(timeLeft);
var x = window.setInterval(function() {
var timer = Seconds;
if(timer === -1) { clearInterval(x); return; }
$('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
Seconds--;
},1000);
}
I have this code. Everything works fine, when this tab is active in browser, but when I change tab and return in tab later it has problems. To be more precise, it Incorrectly displays the time.
I'd also tried setTimeout, but problem was the same.
One idea, which I have is: HTML5 Web Workers...
But here is another problem... browsers support.
can someone help to solve this problem?
How can I write setInterval, which works properly,even when tab is not active
Use the Date object to calculate time. Don't rely on a timer firing when you ask it to (they are NOT real-time) because your only guarantee is that it'll not fire before you ask it to. It could fire much later, especially for an inactive tab. Try something like this:
function initTimer(periodInSeconds) {
var end = Date.now() + periodInSeconds * 1000;
var x = window.setInterval(function() {
var timeLeft = Math.floor((end - Date.now()) / 1000);
if(timeLeft < 0) { clearInterval(x); return; }
$('#div').html('00:' + (timeLeft < 10 ? '0' + timeLeft : timeLeft));
},200);
}
initTimer(10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div"></div>
Note that by checking it more frequently we can make sure it's never off by too much.
JavaScript timers are not reliable, even when the tab is active. They only guarantee that at least as much time as you specified has passed; there is no guarantee that exactly that amount of time, or even anything close to it, has passed.
To solve this, whenever the interval fires, note what time it is. You really only need to keep track of two times: the current time, and the time that the previous interval fired. By subtracting the previous tick's time from the current tick's time, you can know how much time has actually passed between the two, and run your calculations accordingly.
Here's a basic outline of how something like this might look:
function initTimer(timeLeft) {
var Me = this,
TotalSeconds = 35,
Seconds = Math.floor(timeLeft),
CurrentTime = Date.now(),
PreviousTime = null;
var x = window.setInterval(function() {
var timer = Seconds,
timePassed;
PreviousTime = CurrentTime;
CurrentTime = Date.now();
timePassed = CurrentTime - PreviousTime;
if(timer < 0) { clearInterval(x); return; }
$('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
Seconds = Seconds - timePassed;
},1000);
}

How to deal with Javascript timer innacuracy?

So I tried to implement an accurate timer in Javascript via the answer under the accepted answer in this SO post. The only change I made was to initialize an event_last_occurrence_time which occurs on some Javascript event initialization such as the opening of a lightbox. The idea is that every 4 seconds, I'll close a lightbox that is popped up when the page is first opened.
What I notice is that the lightbox actually closes in about 1-2 seconds as opposed to 4 seconds on the first instance of the browser launch. So I did console.log(elapsed-event_last_occurrence_time) and kept track on my stopwatch - it seems that the timing mechanism below moves faster than real-world time on initialization at least (I can see this via the console.log - it jumps to 5-10 seconds while my stopwatch is still around ~2 seconds.
1) Is this just the nature of the timing mechanisms in Javascript or is there an obvious flaw in the algorithm below that I'm missing?
var start = new Date().getTime(),
time = 0,
elapsed = '0.0'
event_last_occurrence_time = elapsed;
function instance()
{
time += 100;
elapsed = Math.floor(time / 100) / 10;
if(Math.round(elapsed) == elapsed) { elapsed += '.0'; }
if ((elapsed-event_last_occurrence_time)%4==0) { $.lightBox.close() }
document.title = elapsed;
var diff = (new Date().getTime() - start) - time;
window.setTimeout(instance, (100 - diff));
}
window.setTimeout(instance, 100);
$("#some_id").click(function(e)
{
$.lightBox({
onOpen: function ()
{
instance();
event_last_occurrence_time = elapsed;
}
});
});

Actionscript 2 Setinterval add milliseconds to timer

I have set my setInterval to 10 seconds. And it all working fine in my game, it count down from 10 seconds and change scene when it hit 0.
The problem is that I really would need to show milliseconds to and I cant understand how I will add it to the counter... It shouldnt be hard at all but I really cant figure it out.
Here is the script:
timer = 10;
clearInterval(countdownInterval);
countdown = function(){
timer--;
if (timer ==0){
gotoAndPlay("Scene 1",2 );
}
}
countdownInterval = setInterval(countdown,1000);
You probably need a Date() object which will report time deltas in milliseconds. Using setTimout to increment a timer is likely to have a number of problems.
var startTime = +(new Date) + (10 * 1000);
var checkFinished = function() {
timeRemaining = startTime - (new Date);
if(timeRemaining <= 0) {
gotoAndPlay("Scene 1",2 );
} else {
setTimeout(checkFinished, 100)l
}
}
setTimeout(checkFinished, 0);

Executing code inside setInterval function only once per few seconds

I'm working on a simple project that is HTML and Javascript; and I have a problem with my timer.
I'm calculating the seconds between two Date() objects; and every 2 seconds, I want to get a new random number. I have a setInterval that runs every 100 ms and when I get past the 2 second mark, the code inside the if statement should run.
So my question is:
How can I make sure the code execute only once per 2 seconds in an if statement that is inside a setInterval() that runs every 100 ms?
Here is the code:
var startTime = new Date();
var endTime = new Date();
var randomNumber = 0;
var gameTimer = setInterval(function(){
//calculate seconds;
var secondsPassed = Math.round( (endTime - startTime) / 1000 );
if(modulo(secondsPassed,2) == 0){
//when the "gate" is open this keep executing every 100 mili seconds.
//but i want it to execute only once every 2 seconds.
randomNumber = Math.floor(Math.random()*lanes.length);
$(lanes[randomNumber]).append(box);
}
endTime = new Date();
}, 100);
var modulo = function (n, m) {
var remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};
I think you are asking for a double-interval timer.
var interval = 100, beat = 2000, ticks = 0;
var timer = setInterval(function(){
runsEvery100ms(); // ««« Code here runs every 100 ms.
if (ticks > 0 && ticks % beat === 0) {
runsEvery2000ms(); // ««« Code here runs every 2000 ms.
ticks = 0;
}
ticks += interval;
}, interval);
Demo Fiddle here.

Categories