I am working on knockout js.
In that i have a recursive function which executes a function every minute. for that am using a timer every 60 sec it will execute also same will be reflecting in the UI also.
In my case, if i try to assign or initialize a timer value(observable) which is inside a loop, it doesn't reflecting instead of reflecting it is added to the pipeline and that much time loop is running simultaneously.
In that case i want to kill the loop and again want to restart every time i am changing the timer value.
timerInSec=60;
var loop = function () {
if (this.timer() < 1) {
myFunction()
this.timer(this.timerInSec - 1);
setTimeout(loop, 1000);
} else {
this.timer(this.timer() - 1);
setTimeout(loop, 1000);
}
};
loop();
Here is my solution. Please check.
timerInSec = 60;
const Loop = (function () {
let timer = 0;
let timerId = -1;
const myFunction = function () {
console.log('finished');
}
const fnLog = function (tm) {
console.log('current time = ', tm);
}
const fnProc = function () {
timerId = setTimeout(myFunction, 1000 * timer);
}
return {
start: function (tm = 60) {
this.stop();
timer = tm;
fnProc();
},
stop: function () {
if (timerId !== -1) {
clearTimeout(timerId);
timerId = -1;
}
}
}
})();
Loop.start(timerInSec);
setTimeout(() => {
Loop.start(timerInSec);
}, 500);
Related
when i click my button, a timer is supposed to display a countdown timer. But the button does not work.
let timerCounter = document.getElementById("timer-counter");
let timer;
let timerCount;
function startTimer() {
timer = setInterval(function() {
timerCount--;
timerElement.textContent = "Time; " + timerCount;
if (timerCount === 0) {
clearInterval(timer);
}
});
}
startButton.addEventListener("click", startTimer);
This is what I found so far:
You are decrementing the timerCount, need to specify the initial value for it to work.
You're using timerElement instead of timerCounter that you've declared.
You must pass the second args to the setInterval which is delay.
const timerCounter = document.getElementById('timer-counter');
const startButton = document.getElementById('start-button');
let timer;
let timerCount = 30;
startButton.addEventListener('click', startTimer);
function startTimer() {
timer = setInterval(function () {
timerCount--;
timerCounter.textContent = 'Time; ' + timerCount;
if (timerCount === 0) {
clearInterval(timer);
}
}, 1000);
}
<div id="timer-counter"></div>
<button id="start-button">Start</button>
Here's a slightly different approach that avoids some of the problems with global variables. The function the listener calls initialises the count, and then returns a new function (a closure) that is called when the button is clicked. It also uses setTimeout which I find more easy to understand.
// Cache your elements
const counter = document.querySelector('#counter');
const startButton = document.querySelector('button');
// Initialise your count variable
function startTimer(count = 30) {
// Return a function that is called from
// the listener
return function loop () {
// Disabled the button once it's been clicked
if(!startButton.disabled) startButton.disabled = true;
counter.textContent = `Time: ${count}`;
if (count > 0) {
setTimeout(loop, 500, --count);
}
}
loop();
}
// Call startTimer to initialise the count, and return
// a new function that is used as the listener
startButton.addEventListener('click', startTimer(), false);
<div id="counter"></div>
<button>Start</button>
I'm sure this could be improved.
In this example we don't go below 0.
We don't allow timeout collisions ( timeouts don't stack causing weird counting speeds ).
We can reset to the original number when on 0.
const c = document.getElementById('timer-counter')
const b = document.getElementById('start-button')
let timer = false
let timerCount = 30
b.addEventListener('click', start)
function decrement() {
if(timerCount < 0) {
timerCount = 30
timer = false
return
}
c.innerText = `Count: ${timerCount}`
timerCount--
timer = setTimeout(decrement, 200)
}
function start() {
if(timer) return
decrement()
}
<div id="timer-counter"></div>
<button id="start-button">Start</button>
I need to exit from a running interval if the conditions are correct:
var refreshId = setInterval(function() {
var properID = CheckReload();
if (properID > 0) {
<--- exit from the loop--->
}
}, 10000);
Use clearInterval:
var refreshId = setInterval(function() {
var properID = CheckReload();
if (properID > 0) {
clearInterval(refreshId);
}
}, 10000);
Pass the value of setInterval to clearInterval.
const interval = setInterval(() => {
clearInterval(interval);
}, 1000)
Demo
The timer is decremented every second, until reaching 0.
let secondsRemaining = 10
const interval = setInterval(() => {
// just for presentation
document.querySelector('p').innerHTML = secondsRemaining
// time is up
if (secondsRemaining === 0) {
clearInterval(interval);
}
secondsRemaining--;
}, 1000);
<p></p>
Updated for ES6
You can scope the variable to avoid polluting the namespace:
const CheckReload = (() => {
let counter = - 5;
return () => {
counter++;
return counter;
};
})();
{
const refreshId = setInterval(
() => {
const properID = CheckReload();
console.log(properID);
if (properID > 0) {
clearInterval(refreshId);
}
},
100
);
}
This code should run for 10 seconds before ending, however if you are running the function again before the 10 seconds are finished, it should clear theTimeout and start the 10 seconds over again
function start() {
let counter = 0;
let timeUp = true;
let hello;
setInterval(()=> {
counter++
console.log(counter)
},1000);
if (timeUp == false) {
clearTimeout(hello)
timeUp = true
console.log('should run again with new clock')
start()
} else {
console.log('new clock started')
timeUp = false;
hello = setTimeout(() => {
timeUp = true
console.log('end clock')
}, 10000);
};
};
When you call start() again, this new function has no reference to hello or timeUp
Try it like this:
let hello
let timeUp = true
function start() {
let counter = 0;
//let timeUp = true;
//let hello;
setInterval(()=> {
counter++
console.log(counter)
},1000);
if (timeUp == false) {
clearTimeout(hello)
timeUp = true
console.log('should run again with new clock')
start()
} else {
console.log('new clock started')
timeUp = false;
hello = setTimeout(() => {
timeUp = true
console.log('end clock')
}, 10000);
};
};
window.start = start
Inside your function start, timeUp is always set to true, and thus clearTimeout will never be called. The way you're doing things, you should make timeUp a global variable so the function has "memory" of if the time has been reached or not.
But why do you need to set two intervals? You're already keeping track of the number of seconds that have passed, so we can make use of that interval to determine when 10 seconds have passed. This simplifies things quite a bit, and allows us to get rid of the timeUp variable as well:
let interval;
function start() {
let counter = 0;
clearInterval(interval); // clear the previous interval
interval = setInterval(() => { // set a new interval
counter++;
if (counter == 10) {
console.log('end of clock');
clearInterval(interval);
}
console.log(counter);
}, 1000);
}
This achieves exactly what you want. Whenever start is called, it cancels the previous interval and creates a new one. Once 10 seconds have passed, it clears the interval.
Your approach is kind of misleading. I think a better approach would be to have a Timer Object that you can start:
function Timer() {
var self = {
// Declare a function to start it for a certain duration
start: function(duration){
self.counter = 0;
self.duration = duration;
clearTimeout(self.timeout); // Reset previous timeout if there is one
console.log("New counter starting.");
self.count();
},
// A function to count 1 by 1
count: function(){
console.log(self.counter);
self.counter++;
if(self.counter > self.duration){
console.log('Time is up.');
} else {
self.timeout = setTimeout(self.count, 1000); // not over yet
}
}
// and other functions like stop, pause, etc if needed
};
return self;
}
// Declare your Timer
var myTimer = new Timer();
// Start it on click
document.getElementById('start-btn').addEventListener('click', function(){
myTimer.start(10);
}, true);
<button id="start-btn">Start the timer</button>
I'm trying to create a simple countdown timer. It counts down from the number entered.
However, I'm trying to clear the interval when the counter gets to 0. At the moment it seems to acknowledge the if statement, but not clearInterval().
http://jsfiddle.net/tmyie/cf3Hd/
$('.click').click(function () {
$('input').empty();
var rawAmount = $('input').val();
var cleanAmount = parseInt(rawAmount) + 1;
var timer = function () {
cleanAmount--;
if (cleanAmount == 0) {
clearInterval(timer);
}
$('p').text(cleanAmount);
};
setInterval(timer, 500);
})
You're not saving the return value of the call to setInterval, which is the value that needs to be passed to clearInterval. Passing the timer handler does no good.
var timer, timerHandler = function () {
cleanAmount--;
if (cleanAmount == 0) {
clearInterval(timer);
}
$('p').text(cleanAmount);
};
timer = setInterval(timerHandler, 500);
(function() {
var count = {
digit: 0,
increment: function() {
var interval = setInterval(function() {
if (++count.digit == 10) {
clearInterval(interval);
count.decrement();
}
var update = document.getElementById("liveUpdate");
update.innerHTML = count.digit;
}, 500);
},
decrement: function() {
var interval = setInterval(function() {
if (--count.digit == -1) {
clearInterval(interval);
}
}, 500);
}
};
count.increment();
})();
It stops but it doesn't go down? What could be the problem?
Your decrement function never updates the output anywhere. The variable is going down but you don't show that on screen.
Try (or check the corresponding JSFiddle):
(function() {
var update = document.getElementById("liveUpdate");
var count = {
digit: 0,
increment: function() {
var interval = setInterval(function() {
if (++count.digit == 10) {
clearInterval(interval);
count.decrement();
}
update.innerHTML = count.digit;
}, 500);
},
decrement: function() {
var interval = setInterval(function() {
if (--count.digit == -1) {
clearInterval(interval);
}
update.innerHTML = count.digit;
}, 500);
}
};
count.increment();
})();
setInterval will call the function every 500 seconds. It will not stop until you stop it. You can read more about stopping it at Stop setInterval call in JavaScript
It't not a bug, it's a feature ;-). setInterval() runs the given function in a loop with a given interval (500 ms). See this article for details.