Make a timer using setInterval() - javascript

I'm trying to make a timer in javascirpt and jQuery using the setInterval function.
The timer should count down from 90 to zero (seconds).
The code that I'm using for this:
setInterval(settime(), 1000);
in this settime() sets the var time (started on 90) -1, this action has to happen once every second.
My problem is that I don't get how to let this action happen 90 times; I tried using a for loop but then the counter counts from 90 to 0 in 1 second.
Does anyone knows a better alternative?

Something like this should do the trick:
var count = 90;
var interval = setInterval(function(){
setTime();
if (count === 0){
clearInterval(interval); // Stopping the counter when reaching 0.
}
}, 1000);
I don't have the code you need but I'm sure you'll need to update the count at some point on your page.
You can cancel an interval with clearInterval which needs the ID of the interval that's created when you call setInterval

function timer(seconds, cb) {
var remaningTime = seconds;
window.setTimeout(function() {
cb();
console.log(remaningTime);
if (remaningTime > 0) {
timer(remaningTime - 1, cb);
}
}, 1000);
}
var callback = function() {
console.log('callback');
};
timer(90, callback);
Caution in using setInterval, may not work as you expect http://bonsaiden.github.io/JavaScript-Garden/#other.timeouts

setInterval keeps calling your function at each second (since you use 1000).
So setInterval expects a function as its first argument, which is the function which will be called periodically. But instead of passing settime, you pass its returned value. That won't work, unless settime returns a function.
Instead, try
setInterval(settime, 1e3);

Try utilizing .data() , .queue() , animate() , .promise() ; to stop "countdown" can call $(element).clearQueue("countdown")
var counter = function counter(el) {
return $(el || window).data({
"start": {
"count": 0
},
"stop": {
"count": 1
},
"countdown": $.map(Array(90), function(val, key) {
return key
}).reverse(),
"res": null
})
.queue("countdown", $.map($(this).data("countdown")
, function(now, index) {
return function(next) {
var el = $(this);
$($(this).data("start"))
.animate($(this).data("stop"), 1000, function() {
el.data("res", now)
$("pre").text(el.data("res"));
next()
});
}
})
)
.promise("countdown")
.then(function() {
$("pre").text($(this).data("res"))
.prevAll("span").text("countdown complete, count:");
});
};
$("button").on("click", function() {
if ($(this).is("#start")) {
counter();
$("pre").text(90).prev("span").html("");
$(window).dequeue("countdown");
}
else {
$(window).clearQueue("countdown").promise("countdown")
.then(function() {
$("pre").prevAll("span").html(function(_, html) {
return html.replace("complete", "stopped")
});
})
}
});
pre {
font-size:36px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<button id="start">start</button><button id="stop">stop</button>
<br />
<span></span>
<br />
<pre>90</pre>

Related

Recursive function called in setTimeout is executing even after navigated to other Angular components

It became challenging for me to stop executing a recursive function that is used to display a progress bar even after navigating to different component.
animateProgress() {
var counter = this.incrementCounter; //initial value = 0
if (counter <= 100) {
this.updateProgressBar(counter);
setTimeout(()=>{
this.animateProgress();
}, 3000);
this.incrementCounter++;
}
else {
return false;
}
}
updateProgressBar(percentage) {
$('.progressBarDiv').css("width", percentage + "%");
}
I think you should use setInterval since you want that part of code to be repeated multiple times.
animateProgress() {
// removed the local variable counter cause it wasn't really necessary
// setInterval returns an id that you can later use to cancel the interval
const interval = setInterval(() => {
if (this.incrementCounter <= 100) {
this.updateProgressBar();
this.incrementCounter++;
}
else {
// when you reach the condition you clear the inverval
clearInterval(interval);
}
}, 3000);
}
updateProgressBar() {
$('.progressBarDiv').css("width", this.incrementCounter + "%");
}
Otherwise if you wish to stick with setTimeout and recursion this whould work:
animateProgress() {
if (this.incrementCounter <= 100) {
this.updateProgressBar();
this.incrementCounter++;
setTimeout(()=>{
this.animateProgress();
}, 3000);
}
}

Reset interval after clearing it

I have this code:
var int1 = setInterval(function () {
// do stuff
if(//stuff done){
clearInterval(int1);
setTimeout(
function () {
setInterval(int1)
}
,60000);
}}
}, 1000)
and want the interval to be running again after 60 seconds but setInterval(int1) doesn't seem to trigger it again. What am I doing wrong?
EDIT: full code: http://pastie.org/8704786
That'd because int1 is not a function, but an interval id. Try this instead:
var int1;
var func = function () {
// do stuff
if(//stuff done){
clearInterval(int1);
setTimeout(func, 60000);
}
};
int1 = setInterval(func, 1000);
You did 2 mistakes:
setInterval whant a function, while int1 contains an interval handle
You didn't pass amount of time in your setInterval call
What you want probably is:
var int1;
function scheduleStuff() {
int1 = setInterval(doStuff, 1000);
}
function doStuff() {
// do stuff
if(/*stuff done*/){
clearInterval(int1);
setTimeout(scheduleStuff,60000);
}}
}
scheduleStuff();
set intervall expectes a function wich is called after waiting time...
this line is wrong:
setInterval(int1)
no function and no waiting time given...

Javascript: Force new loop iteration in setInterval

I have a setInterval loop. It's set to 3500 milliseconds, like so:-
var loop = setInterval(function() { /*stuff*/ }, 3500);
At one point in 'stuff' if a certain situation occurs, I want to force a new iteration of the loop and NOT WAIT for the 3500 milliseconds. How is that possible? Is it continue or do I just need to frame the process differently?
You could try writing an anonymous self-calling function using setTimeout instead of setInterval:
var i = 0;
(function() {
// stuff
i++;
if (i % 2 == 0) {
// If some condition occurs inside the function, then call itself once again
// immediately
arguments.callee();
} else {
// otherwise call itself in 3 and a half seconds
window.setTimeout(arguments.callee, 3500);
}
})();​ // <-- call-itself immediately to start the iteration
UPDATE:
Due to a disagreement expressed in the comments section against the usage of arguments.callee, here's how the same could be achieved using a named function:
var i = 0;
var doStuff = function() {
// stuff
i++;
if (i % 2 == 0) {
// If some condition occurs inside the function, then call itself once again
// immediately
doStuff();
} else {
// otherwise call itself in 3 and a half seconds
window.setTimeout(doStuff, 3500);
}
};
doStuff();
You can use something like this... using setTimeout instead of setInterval...
<script type="text/javascript">
var show;
var done = false;
show = setTimeout(showHideForm, 3500);
function showHideForm() {
// Do something
if(done) {
clearTimeout(show);
show = setTimeout(showHideForm, 2000);
}
}
</script>
clearTimeout takes as argument the handle which is returned by setTimeout.
Use a named function and call it when you want.
var loop = setInterval(loopFunc, 3500);
function loopFunc(){
//do something
}
function anticipate(){
clearInterval(loop); //Stop interval
loopFunc(); //Call your function
loop = setInterval(loopFunc, 3500); //Reset the interval if you want
}
My contrived example:
var time = 3500,
loops = 0,
loop;
(function run(){
var wait = time,
dontwait = false;
if (loops++ == 5) {
loops = 0;
dontwait = 1000;
}
console.log('Interval: ', dontwait || wait);
return loop = setTimeout(run, dontwait || wait);
})();​
http://jsfiddle.net/NX43d/1/
Basically, a self-invoking function looping back on a self-calling function, with (!) shorthand variable switching. Nifty.
function looper(t) {
var loop = setInterval(function() {
document.write(s++);
if (mycondition) { // here is your condition
loopagain(200); // specify the time which new loop will do
loop = window.clearInterval(loop); // clear the first interval
return; // exit from this function!
}
}, t);
}
window.onload = looper(1000); // this will have default setInterval function time ans will start at window load!
function loopagain(t) {
looper(t);
}​
http://jsfiddle.net/tFCZP/

Calling a function every 60 seconds

Using setTimeout() it is possible to launch a function at a specified time:
setTimeout(function, 60000);
But what if I would like to launch the function multiple times? Every time a time interval passes, I would like to execute the function (every 60 seconds, let's say).
If you don't care if the code within the timer may take longer than your interval, use setInterval():
setInterval(function, delay)
That fires the function passed in as first parameter over and over.
A better approach is, to use setTimeout along with a self-executing anonymous function:
(function(){
// do some stuff
setTimeout(arguments.callee, 60000);
})();
that guarantees, that the next call is not made before your code was executed. I used arguments.callee in this example as function reference. It's a better way to give the function a name and call that within setTimeout because arguments.callee is deprecated in ecmascript 5.
use the
setInterval(function, 60000);
EDIT : (In case if you want to stop the clock after it is started)
Script section
<script>
var int=self.setInterval(function, 60000);
</script>
and HTML Code
<!-- Stop Button -->
Stop
A better use of jAndy's answer to implement a polling function that polls every interval seconds, and ends after timeout seconds.
function pollFunc(fn, timeout, interval) {
var startTime = (new Date()).getTime();
interval = interval || 1000;
(function p() {
fn();
if (((new Date).getTime() - startTime ) <= timeout) {
setTimeout(p, interval);
}
})();
}
pollFunc(sendHeartBeat, 60000, 1000);
UPDATE
As per the comment, updating it for the ability of the passed function to stop the polling:
function pollFunc(fn, timeout, interval) {
var startTime = (new Date()).getTime();
interval = interval || 1000,
canPoll = true;
(function p() {
canPoll = ((new Date).getTime() - startTime ) <= timeout;
if (!fn() && canPoll) { // ensures the function exucutes
setTimeout(p, interval);
}
})();
}
pollFunc(sendHeartBeat, 60000, 1000);
function sendHeartBeat(params) {
...
...
if (receivedData) {
// no need to execute further
return true; // or false, change the IIFE inside condition accordingly.
}
}
In jQuery you can do like this.
function random_no(){
var ran=Math.random();
jQuery('#random_no_container').html(ran);
}
window.setInterval(function(){
/// call your function here
random_no();
}, 6000); // Change Interval here to test. For eg: 5000 for 5 sec
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="random_no_container">
Hello. Here you can see random numbers after every 6 sec
</div>
setInterval(fn,time)
is the method you're after.
You can simply call setTimeout at the end of the function. This will add it again to the event queue. You can use any kind of logic to vary the delay values. For example,
function multiStep() {
// do some work here
blah_blah_whatever();
var newtime = 60000;
if (!requestStop) {
setTimeout(multiStep, newtime);
}
}
Use window.setInterval(func, time).
A good example where to subscribe a setInterval(), and use a clearInterval() to stop the forever loop:
function myTimer() {
}
var timer = setInterval(myTimer, 5000);
call this line to stop the loop:
clearInterval(timer);
Call a Javascript function every 2 second continuously for 10 second.
var intervalPromise;
$scope.startTimer = function(fn, delay, timeoutTime) {
intervalPromise = $interval(function() {
fn();
var currentTime = new Date().getTime() - $scope.startTime;
if (currentTime > timeoutTime){
$interval.cancel(intervalPromise);
}
}, delay);
};
$scope.startTimer(hello, 2000, 10000);
hello(){
console.log("hello");
}
function random(number) {
return Math.floor(Math.random() * (number+1));
}
setInterval(() => {
const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';//rgb value (0-255,0-255,0-255)
document.body.style.backgroundColor = rndCol;
}, 1000);
<script src="test.js"></script>
it changes background color in every 1 second (written as 1000 in JS)
// example:
// checkEach(1000, () => {
// if(!canIDoWorkNow()) {
// return true // try again after 1 second
// }
//
// doWork()
// })
export function checkEach(milliseconds, fn) {
const timer = setInterval(
() => {
try {
const retry = fn()
if (retry !== true) {
clearInterval(timer)
}
} catch (e) {
clearInterval(timer)
throw e
}
},
milliseconds
)
}
here we console natural number 0 to ......n (next number print in console every 60 sec.) , using setInterval()
var count = 0;
function abc(){
count ++;
console.log(count);
}
setInterval(abc,60*1000);
I see that it wasn't mentioned here if you need to pass a parameter to your function on repeat setTimeout(myFunc(myVal), 60000); will cause an error of calling function before the previous call is completed.
Therefore, you can pass the parameter like
setTimeout(function () {
myFunc(myVal);
}, 60000)
For more detailed information you can see the JavaScript garden.
Hope it helps somebody.
I favour calling a function that contains a loop function that calls a setTimeout on itself at regular intervals.
function timer(interval = 1000) {
function loop(count = 1) {
console.log(count);
setTimeout(loop, interval, ++count);
}
loop();
}
timer();
There are 2 ways to call-
setInterval(function (){ functionName();}, 60000);
setInterval(functionName, 60000);
above function will call on every 60 seconds.

Best way to have event occur n times?

I use the following code to create countdowns in Javascript. n is the number of times to repeat, freq is the number of milliseconds to wait before executing, funN is a function to call on each iteration (typically a function that updates part of the DOM) and funDone is the function to call when the countdown is complete.
function timer(n, freq, funN, funDone)
{
if(n == 0){
funDone();
}else{
setTimeout(function(){funN(n-1); timer(n-1, freq, funN, funDone);}, freq);
}
}
It can be called like so:
timer(10,
1000, /* 1 second */
function(n){console.log("(A) Counting: "+n);},
function() {console.log("(A) Done!");}
);
timer(10,
500,
function(n){console.log("(B) Counting: "+n);},
function() {console.log("(B) Done!");}
);
The advantage of this is that I can call timer() as many times as I want without worrying about global variables etc. Is there a better way to do this? Is there a clean way to make setInterval stop after a certain number of calls (without using global variables)? This code also creates a new lambda function with each call to setTimeout which seems like it could be problematic for large countdowns (I'm not sure how javascript's garbage collector handles this).
Is there a better way to do this? Thanks.
This is basically the same idea as #balabaster, but it is tested, uses prototype, and has a little more flexible interface.
var CountDownTimer = function(callback,n,interval) {
this.initialize(callback,n,interval);
}
CountDownTimer.prototype = {
_times : 0,
_interval: 1000,
_callback: null,
constructor: CountDownTimer,
initialize: function(callback,n,interval) {
this._callback = callback;
this.setTimes(n);
this.setInterval(interval);
},
setTimes: function(n) {
if (n)
this._times = n
else
this._times = 0;
},
setInterval: function(interval) {
if (interval)
this._interval = interval
else
this._interval = 1000;
},
start: function() {
this._handleExpiration(this,this._times);
},
_handleExpiration: function(timer,counter) {
if (counter > 0) {
if (timer._callback) timer._callback(counter);
setTimeout( function() {
timer._handleExpiration(timer,counter-1);
},
timer._interval
);
}
}
};
var timer = new CountDownTimer(function(i) { alert(i); },10);
...
<input type='button' value='Start Timer' onclick='timer.start();' />
I'd create an object that receives a counter and receives a function pointer to execute, something akin to the following pseudo code:
TimedIteration = function(interval, iterations, methodToRun, completedMethod){
var counter = iterations;
var timerElapsed = methodToRun; //Link to timedMethod() method
var completed = callbackMethod;
onTimerElapsed = function(){
if (timerElapsed != null)
timerElapsed();
}
onComplete = function(){
if (completed != null)
completed();
}
timedMethod = function(){
if (counter != null)
if (counter > 0) {
setTimeOut(interval, onTimerElapsed);
counter--;
}
else
onComplete();
this = null;
}
}
if ((counter != null)&&(counter > 0)){
//Trip the initial iteration...
setTimeOut(interval, timedMethod);
counter--;
}
}
obviously this is pseudo code, I've not tested it in an IDE and syntactically I'm not sure if it'll work as is [I'd be astonished if it does], but basically what you're doing is you're creating a wrapper object that receives a time interval, a number of iterations and a method to run upon the timer elapsed.
You'd then call this on your method to run like so:
function myMethod(){
doSomething();
}
function doWhenComplete(){
doSomethingElse();
}
new TimedIteration(1000, 10, myMethod, doWhenComplete);
I like your original solution better than the proposed alternatives, so I just changed it to not create a new function for every iteration (and the argument of fun() is now the value before decrement - change if needed...)
function timer(n, delay, fun, callback) {
setTimeout(
function() {
fun(n);
if(n-- > 0) setTimeout(arguments.callee, delay);
else if(callback) callback();
},
delay);
}

Categories

Resources