EDIT & UPDATE: for reference I rewrote the whole thing with only 1 timer and a second to time converter. Very clean and less complex. Here is the full code: http://pastebin.com/Hb6cBryL
I got this timer that I built out of javascript: http://powerpoint.azurewebsites.net/
It is quite simple code, but for the final implementation I would need to be able to pause the timer and restart it. I use 2 setIntervalls, 1 for the minutes that triggers every 60s and one for the seconds that triggers every second.
When I pause it I clear the intervals. However when I restart them the minutes restart at the 60 interval and aren't synced with the seconds anymore.
I probably implemented this in a horribly wrong way so I'd like to ask for your advice. 1 idea I had was to continue the inverval but avoid updating the variable and text on the page so that the minutes/seconds stay in sync< However this doesn't sound like an ideal solution to me. All tips are welcome :)
Js code:
var minutes = null, seconds = null, cnt, secs;
function settimer(frm) { if (minutes == null) { cnt = frm.timeinput.value - '1'; secs = '59';} };
function stop() {
clearInterval(minutes);
clearInterval(seconds);
minutes = null;
seconds = null;
document.getElementById("minutes").innerHTML = '00';
document.getElementById("seconds").innerHTML = '00';
}
function pause() {
clearInterval(minutes);
clearInterval(seconds);
}
function runtimer() {
event.preventDefault();
if (minutes == null) {
document.getElementById("minutes").innerHTML = cnt;};
minutes = setInterval(function () {
if (cnt == '0') { stop() } else { cnt -= 1; document.getElementById("minutes").innerHTML = cnt; };
}, 6000);
if (seconds == null) { document.getElementById("seconds").innerHTML = secs; };
seconds = setInterval(function () {
if (secs == '0') { secs = '59' } else { secs -= 1; document.getElementById("seconds").innerHTML = secs; };
}, 100);
}
You'll need to wrap them somehow, and recognise that you can't immediately get the timer's id.
function setIntervalWithOffset(fn, delay, offset) {
var o = {id: null, o_id: null};
o.o_id = window.setTimeout(function () {
o.id = window.setInterval(fn, delay);
}, offset);
return o;
}
function setTimeoutWithOffset(fn, delay, offset) {
var o = {id: null, o_id: null};
o.o_id = window.setTimeout(function () {
o.id = window.setTimeout(fn, delay);
}, offset);
return o;
}
To clear, use window.clearTimeout on obj.o_id and whichever type you set for obj.id.
You should also consider whether you'd be better off implementing a setTimeout loop rather than using setInterval so you don't have a chance of a cascade error
Sorry, I think that you are in a bad way. Why do you want to use two intervals to do the same thing? Intervals are asynchronous, you can not synchronize two intervals that runs independently.
You can achieve that with just one interval. To show seconds, you can just increment another variable each time that your counter reachs a threshold:
var counter = 0;
var seconds = 0;
var $interval = setInterval(function(){
counter++;
if (counter >= 6000) {
counter = counter - 6000;
seconds++;
}
, 10);
So, it will be more easy to stop/restart your interval.
You need to get the handle to the timer, in order to be able to reset it later, you can do like below:
timeoutHandle = setTimeout(function(){/*code*/}, 1000);
clearTimeout(timeoutHandle);
Take a look at this jsfiddle
Taken from : How do I stop a window.setInterval in javascript?
Related
I have interval that needs to do some http requests after one minute
setInterval(() => {
this.takeTableDataCallInterval();
}, 60000);
How can i get counter minus from my Interval Number ?
For example every one second i want to show something like
60 seconds Left until new call is maked
59 seconds Left until new call is maked
When it comes to 0 it should start over
Here is an example:
it works every one second in order to do the countdown but once it reach to the 60 it resets the countdown and does the request.
const timer = document.querySelector('#timer');
let counter = 60;
setInterval(() => {
if (counter === 0) {
//this.takeTableDataCallInterval();
counter = 60;
}
else {
timer.innerHTML = `${counter} seconds left`;
counter--;
}
}, 1000);
<p id="timer"></p>
Counting shorter setInterval periods is one way of doing this, although timings here are rarely accurate enough to decently measure the passage of time, and you'll see drift (i.e. 60 one second intervals won't sum to exactly 60s)
Instead, record a "due time" with a high accuracy using performance.now()
let dueTimeMs = performance.now() + 60000;
then set an interval with relatively short time
setInterval(() => {
const nowMs = performance.now();
const timeUntilDueMs = dueTimeMs - nowMs;
// report remaining time
if(timeUntilDueMs <= 0){
// do something
dueTimeMs += 60000;
}
},100);
Try this:
let timeout;
function resetTimeout(limit) {
timeout = limit;
}
function serviceCall() {
console.log('Service call made')
}
setInterval(() => {
if(timeout == 0 || timeout == null) {
(timeout == 0) ? serviceCall() : ''
resetTimeout(60);
}
console.log(`${timeout}s left until new call is made`)
timeout --;
}, 1000);
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);
}
I made a timer that will reach zero.
and when it reaches zero make the timer run again.
the timer goes back to the starting number but doesnt run again.
also when i call it again the numbers just start to jump.
the code:
var timerPlace = document.getElementById('timer');
var timerP = document.getElementById('timerHard');
var stopTimer;
var toStop;
function timeMed() {
console.log('im in!')
var counter = 0;
var timeLeft = 5;
timerPlace.innerHTML = '00:45';
function timeIt() {
console.log('here')
counter++
timerPlace.innerHTML = convertSeconds(timeLeft - counter);
if (timerPlace.innerHTML == '00:00') {
clearInterval(stopTimer);
resetExercise();
timeMed();
}
}
function convertSeconds(s) {
var sec = s % 60;
var min = Math.floor((s % 3600) / 60);
return ('0' + min).slice(-2) + ':' + ('0' + sec).slice(-2);
}
if (!stopTimer) {
stopTimer = setInterval(timeIt, 1000);
}
}
You only call setInterval() when stopTimer is not set. But after the countdown completes, stopTimer is still set to the ID of the old interval timer, so you don't restart it. You should clear the variable when you call clearInterval().
if (timerPlace.innerHTML == '00:00') {
clearInterval(stopTimer);
stopTimer = null;
resetExercise();
timeMed();
}
Modern ES6 Approach and best practices.
I've decided to take the chance and refactor your code a little with Javascripts best practices in mind.
I've added comments which explain the code, and the engineering considerations.
The baseline for the timer is taken from the excellent answer here: https://stackoverflow.com/a/20618517/1194694
// Using destructuring on the paramters, so that the keys of our configuration object,
// will be available as separate parameters (avoiding something like options.duraitons and so on.
function startTimer({duration, onUpdate , infinite}) {
let timer = duration, minutes, seconds;
let interval = setInterval(function () {
minutes = parseInt(timer / 60);
seconds = parseInt(timer % 60);
// you can also add hours, days, weeks ewtc with similar logic
seconds = seconds < 10 ? `0${seconds}` : seconds;
minutes = minutes < 10 ? `0${minutes}` : minutes;
// calling your onUpdate function, passed from configuraiton with out data
onUpdate({minutes, seconds});
if (--timer < 0) {
// if infinite is true - reset the timer
if(infinite) {
timer = duration;
} else {
// Clearing the interval + additonal logic if you want
// I would also advocate implementing an onEnd function,
// So that you'll be able to decide what to do from configuraiton.
clearInterval(interval);
}
}
}, 1000);
}
const duration = 5;
const displayElement = document.querySelector("#timer");
startTimer({
duration,
onUpdate: ({minutes, seconds}) => {
// now you're not constraint to rendering it in an element,
// but can also Pass on the data, to let's say your analytics platform, or whatnot
displayElement.textContent = `${minutes}:${seconds}`;
},
infinite: true
});
<div id="timer">
</div>
I'm creating pomodoro timer- interval should repeat with different duration after first one completes. simplified non working exampe:
var firstDuration=5;
var secondDuration=10;
var timer=setInterval(()=>{
firstDuration--
if (firstDuration<0){
clearInterval(timer) ..
//secondDuration-- dont know how to continue..
What is the best way to implement such functionality? Also i plan to use Date.now() rather than -- .
If i've understood the requirements correctly, this will do what you want. It will have a timer go off every second until 20 minutes have elapsed, then every second until 5 minutes have elapsed. At that point it starts over with the 20 minute countdown.
const workDurationSeconds = 20 * 60;
const breakDurationSeconds = 5 * 60;
function startCountdown(session) {
let duration;
if (session === 'work') {
duration = workDurationSeconds;
} else {
duration = breakDurationSeconds;
}
let id = setInterval(() => {
duration--;
if (duration <= 0) {
clearInterval(id);
startCountdown(session === 'work' ? 'break' : 'work');
}
}, 1000);
}
This question already has answers here:
Stop setInterval
(6 answers)
Closed 4 years ago.
I am creating a simple JavaScript Timer. Firstly, here's my code that I'm working with:
//Variables used for the timer
var timer = "waiting",
seconds = 0,
minutes = 0,
extraFill1 = "",
extraFill2 = "";
//Check whether to start or stop the timer
function toggleClock() {
if (timer === "waiting") {
setInterval(start, 1000);
timer = "executing";
document.getElementById("btn").innerText = "Stop";
}
else {
clearInterval(start);
timer = "waiting";
document.getElementById("btn").innerText = "Start";
}
}
//Increment seconds and display correctly
function start() {
seconds++;
//Add a leading zero for 1 digit numbers (seconds)
if (seconds < 10 || seconds === 60) {
extraFill1 = "0";
}
else {
extraFill1 = "";
}
//Increment minute when seconds reaches 60
if (seconds === 60) {
minutes += 1;
seconds = 0;
}
//Add a leading zero for 1 digit numbers (minutes)
if (minutes < 10) {
extraFill2 = "0";
}
else {
extraFill2 = "";
}
//display results
document.getElementById("result").innerHTML = extraFill2 + minutes + ":" + extraFill1 + seconds;
}
In my first function toggleClock(), I have stated that if timer !== waiting, then we do clearInterval(start). I would like to clearInterval(start) if timer === "executing. This does not work (which I think is because it has a local scope?). To solve this, I attempted writing:
var myTimer = setInterval(start, 1000);
I planned on calling myTimer when I wanted to start the timer. Instead, the interval kicks off as soon as the page is loaded (and the variable is declared).
How might I set an interval of a function (on button click) with the ability to stop/clear the interval (by pressing the same button) later?
You need to pass to clearInterval the result of your call to setInterval earlier; you don't pass a function to clearInterval, you pass it the intervalID. For example:
let clockInterval;
function toggleClock() {
if (timer === "waiting") {
clockInterval = setInterval(start, 1000);
timer = "executing";
document.getElementById("btn").innerText = "Stop";
}
else {
clearInterval(clockInterval);
timer = "waiting";
document.getElementById("btn").innerText = "Start";
}
}