I have a timer function and I want to clear the timeouts or reset the function, cause every time I execute it, a new timeouts are created, so I recieve several counts.
My idea is to reset the count every time I execute the function. I only want a 1 instance of timer and get the correct count. If if execute several times the function I want to restart to 0.
Here is my code:
var timeouts = new Array();
var timer = null;
io.sockets.on('connection', function (client)
{
client.on("start", function (){
console.log('Someone has pressed Start button',new Date().getTime());
//try to kill all timeouts
for (var timeout in timeouts) {
clearTimeout(timeout);
};
if(this.timer == null) {
this.timer = new timer(1000, function (data) {
io.sockets.emit('timeupdate', data);
})
}else {
this.timer = null;
});
});
function timer(delay, callback)
{
// self-reference
var self = this;
if (!(this instanceof timer)) {
return new timer();
}
// attributes
var counter = 0;
var start = new Date().getTime();
/**
* Delayed running of the callback.
*/
function delayed()
{
console.log(counter);
callback(counter);
counter ++;
var diff = (new Date().getTime() - start) - counter * delay;
var timeOut = setTimeout(delayed, delay - diff);
timeouts.push(timeOut);
}
// start timer
delayed();
var timeout = setTimeout(delayed, delay);
timeouts.push(timeout);
}
Thank you in advance.
Using clearTimeout() is the correct way. The problem is your for-loop. This might look like a classic foreach-loop, but it is not. You have to do:
for (var i=0; i< timeouts.length; i++) {
clearTimeout(timeouts[i]);
}
Alternatively, also I don't like this personally:
for (var i in timeouts) {
clearTimeout(timeouts[i]); // note how the array is indexed using var i
}
This is a common JavaScript pitfall - the for (x in y)-loop actually iterates over the array's indices, not the values. It can also iterate over an object's properties. Try it out:
var a = [3, 2, 5, 8];
for (var i in a) {
console.log(i);
console.log(a[i]);
}
var o = { test: 'hello', number: 1234 };
for (var x in o)
console.log(x);
Related
I want to set timer-based for loop in JavaScript.
for (var i = 0; i < 20; i++) {
console.log(i)
}
How I can I repeat this loop every second and show the value of i (the counter)?
if you want to control your loops wait time you can combine settimeout with recursion
var i = 0;
function callMe() {
var timetowait = 100;
// some condition and more login
i++;
if(i < 20) {
setTimeout(callMe, timetowait);
}
}
callMe();
I think this is what you are looking for:
var counter = 0;
setInterval( function(){
console.log(counter);
counter++;
},1000);
You can try this approach too:
function loop(start, end, delay, fn) {
if (start > end) return;
function step(){
// callback fn with current iteration and
// recursively calls loop
fn(start);
loop(start + 1, end, delay, fn);
}
setTimeout(step, delay);
}
usage :
loop(1, 20, 1000, console.log)
var i = 0;
function myFunc() {
console.log(i);
i++;
if(i == 20) {
clearInterval(interval);
}
}
var interval = setInterval(myFunc, 1000);
The setInterval() method calls a function or evaluates an expression at -
specified intervals (in milliseconds).
The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.
I'm trying to implement basic 60 sec counter(A p element with idcounter), that is triggered after a button(counter_start()) is pressed.But I want delay of 1 sec between this and make sure this updates in browser window in real-time
<script type="text/javascript">
function counter_start(){
x=0
for(i=0;i<60;i++){
x++;
document.getElementById("counter").innerHTML=x;
}
}
</script>
P.S: There might be other simple methods of implementing a timer.But it's not about timer...actually I'm a student and trying to figure out the architecture and mechanism of this.
EDIT: please post tested versions of the code, as some of em' posted below DO NOT update in real time
Try this Example
Hope it will work for u
JS
for(i = 1; i <= 3; i++)
{
(function(i){
setTimeout(function(){
alert(i);
}, 1000 * i);
}(i));
}
Javascript operates synchronously in the browser.
You need to use setTimeout or setInterval to schedule the for loop's body to be called every second. I'm using setTimeout in the below example for easier "garbage collection"; we will never reschedule the tick to happen after we don't need to update things anymore.
<script type="text/javascript">
var counter = 0;
function counter_tick() {
if(counter < 60) {
counter++;
document.getElementById("counter").innerHTML = counter;
setTimeout(counter_tick, 1000); // Schedule next tick.
}
}
function counter_start() {
counter_tick(); // First update, also schedules next tick to happen.
}
</script>
It sounds like you are looking for a way to pause the current thread, which isn't possible in JavaScript and would probably be a bad idea anyway (the user's browser would lock up while the thread was paused).
A timer is really the way to go with this, otherwise you are fighting the way the language is intended to work.
There is no sleep-function in JS. But you can use window.setTimeout to call a function in given intervals:
function counter_start(){
// get current value
var value = document.getElementById("counter").innerHTML*1;
// leave function if 60 is reached
if(value == 60) {
return;
}
// set the innerHTML to the last value + 1
document.getElementById("counter").innerHTML=value+1;
// call next iteration
window.setTimeout(function(){counter_start()}, 100);
}
counter_start();
JSFiddle-Demo
For-loops run to completion, so you wouldn't usually use one for this.
You just need a timer and a variable to increment:
var maketimer = function(){
var tick = 0,
interval_ms = 1000,
limit = 10,
id;
return {
start: function(){
var timer = this;
console.log('start');
id = setInterval(function(){
if(tick === limit){
timer.stop();
timer.reset();
return;
}
tick += 1;
console.log(tick);
}, interval_ms);
},
stop: function(){
console.log('stop');
clearInterval(id);
},
reset: function(){
console.log('reset');
tick = 0;
}
};
};
var t = maketimer();
t.start();
If you really need to use a for-loop, then you could use a generator function. They're part of the proposed ES6 spec., and you'll need Firefox 26+ to try this out. However the only point of doing this would be to learn about generator functions.
var maketimer = function(){
var interval_ms = 1000,
limit = 10,
id,
loop,
it;
loop = function*(){
var i;
for(i=1; i<=limit; i+=1){
yield i;
}
};
it = loop();
return {
start: function(){
var timer = this;
console.log('start');
id = setInterval(function(){
var tick = it.next();
console.log(tick.value);
if(tick.done){
timer.stop();
timer.reset();
return;
}
}, interval_ms);
},
stop: function(){
console.log('stop');
clearInterval(id);
},
reset: function(){
console.log('reset');
it = loop();
}
};
};
var t = maketimer();
t.start();
Try this::
var x=0;
var myVar;
function myTimer() {
x++;
document.getElementById("counter").innerHTML = x;
if(x==60)
clearInterval(myVar);
}
function counter_start(){
myVar=setInterval(function(){myTimer()},1000);
}
How to call a function 10 times like
for(x=0; x<10; x++) callfunction();
but with 1 sec between each call?
function callNTimes(func, num, delay) {
if (!num) return;
func();
setTimeout(function() { callNTimes(func, num - 1, delay); }, delay);
}
callNTimes(callfunction, 10, 1000);
EDIT: The function basically says: make a call of the passed function, then after a bit, do it again 9 more times.
You can use setInterval for repeated execution with intervals and then clearInterval after 10 invocations:
callfunction();
var callCount = 1;
var repeater = setInterval(function () {
if (callCount < 10) {
callfunction();
callCount += 1;
} else {
clearInterval(repeater);
}
}, 1000);
Added: But if you don't know how long it takes your callfunction to execute and the accurate timings between invocation starting points are not important it seems it's better to use setTimeout for reasons mentioned by Paul S and those described in this article.
Another solution
for(var x=0; x<10; x++) window.setTimeout(callfunction, 1000 * x);
You can try to use setInterval and use a variable to count up to 10. Try this:
var number = 1;
function oneSecond () {
if(number <= 10) {
// execute code here..
number++;
}
};
Now use the setInterval:
setInterval(oneSecond, 1000);
Similar to Amadan's answer but with a different style of closure which means you re-use instead of creating new functions
function call(fn, /* ms */ every, /* int */ times) {
var repeater = function () {
fn();
if (--times) window.setTimeout(repeater, every);
};
repeater(); // start loop
}
// use it
var i = 0;
call(function () {console.log(++i);}, 1e3, 10); // 1e3 is 1 second
// 1 to 10 gets logged over 10 seconds
In this example, if you were to set times to either 0 or Infinity, it would run forever.
I don't know if there's a proper name, but I use a repeater:
function Repeater(callback, delay, count) {
var self = this;
this.timer = setTimeout(function() {self.run();},delay);
this.callback = callback;
this.delay = delay;
this.timesLeft = count;
this.lastCalled = new Date().getTime();
}
Repeater.prototype.run = function() {
var self = this;
this.timesLeft--;
this.callback();
this.lastCalled = new Date().getTime();
if( this.timesLeft > 0) {
this.timer = setTimeout(function() {self.run();},this.delay);
}
}
Repeater.prototype.changeDelay = function(newdelay) {
var self = this;
clearTimeout(this.timer);
this.timer = setTimeout(function() {self.run();},
newdelay-new Date().getTime()+lastcalled);
this.delay = newdelay;
}
Repeater.prototype.changeCount = function(newcount) {
var self = this;
if( this.timesLeft == 0) {
this.timer = setTimeout(function() {self.run();},this.delay);
}
this.timesLeft = newcount;
if( this.timesLeft == 0) clearTimeout(this.timer);
}
You can then use it like this:
new Repeater(callfunction, 1000, 10); // 1 second delay, 10 times
const functionCounterTimer = (callCount) => {
if (callCount < 10) {
setTimeout(() => {
++callCount
console.log("Function Call ", callCount);
functionCounterTimer(callCount);
}, 1000);
}
}
functionCounterTimer(0);
The above was my approach to a similar question.
setInterval(function(){},1000);
Calls the function for every second...
You can also use setTimeout for your thing to work.
I did some digging around on SO and could not find exactly what I am trying to achieve.
In simplistic terms I have a function like
function(){
for(i=0;i<10;i++){
setInterval(function(){ alert(i);), 1000)
}
}
What I would expect is 10 setIntervals that would alert 1 to 10 every 1 second, what happens is it would alert 10 always since 'i' is 10 at the end of for loop. How do I pass 'i' to setInterval anonymous function so that I can preserve the value of i in setInterval?
Above was a simplistic version of my actual problem. I am actually trying to do this
var timers = [];
function(obj){
//Clear any intervals
for(i=0;i<timer.length;i++){
clearInterval(timers[i]);
}
// Empty timers Array
timers = [];
for(i in obj){
//My object from the dom. This guy is what I am trying to preserve
my_obj = document.getElementById(i);
if(obj[i] === "Something"){
timers.push(setInterval(function(){
my_obj.replace_class(["Something", "Otherthing"],"Something");
}, 1000)
}
}
}
my_obj in the above code always refers to id = last 'i' in obj.
Do I make sense?
This should do the trick ;)
for(i = 1; i < 11; i++){
(function(local_i){
setInterval(function(){ console.log(local_i); }, 1000 * local_i)
})(i);
}
You must capture the variable in a closure. In your case this is
function capture(x) {
setInterval(function () {
console.log(x);
}, 1000);
}
for (var i = 0; i < 10; i++) {
capture(i);
}
or
function capture(my_obj) {
var id = setInterval(function() {
my_obj.replace_class(["Something", "Otherthing"],"Something");
}, 1000);
return id;
}
for (i in obj) {
//My object from the dom. This guy is what I am trying to preserve
my_obj = document.getElementById(i);
if (obj[i] === "Something") {
timers.push(capture(my_obj));
}
}
I am trying to loop over an array. However, I would like to add a 15 second delay between each array value. This will write value 1 to console, then count down 15 seconds and write value 2 to console, and so on.
I'm not sure exactly how to do this. My code as of now just outputs the numbers 15 all the way to 1 on the console at once with no actual count down and no array values.
array
["l3", "l4", "l5", "l6", "l7", "l8", "l9", "l10", "l11", "l12", "l13", "l14", "l15", "l16"]
code
var adArray = [];
// get links with class adfu
var adfuClass = document.getElementsByClassName('adfu');
for (var i = 0; i < adfuClass.length; i++) {
var ids = adfuClass[i].id
var newIds = ids.replace(/tg_/i, "l");
adArray.push(newIds);
}
// get links with class ad30
var ad30Class = document.getElementsByClassName('ad30');
for (var i = 0; i < ad30Class.length; i++) {
var ids = ad30Class[i].id;
var newIds = ids.replace(/tg_/i, "l");
adArray.push(newIds);
}
// get links with class adf
var adfClass = document.getElementsByClassName('adf');
for (var i = 0; i < adfClass.length; i++) {
var ids = adfClass[i].id;
var newIds = ids.replace(/tg_/i, "l");
adArray.push(newIds);
}
// loop through array with all new ids
for (var i = 0, l = adArray.length; i < l; i++) {
var counter = 15;
var countDown = setTimeout(function() {
console.log(counter);
if (counter == 0) {
console.log(adArray[i]);
}
counter--;
}, 1000);
}
// loop through array with all new ids
var i = 0, l = adArray.length;
(function iterator() {
console.log(adArray[i]);
if(++i<l) {
setTimeout(iterator, 15000);
}
})();
Something like this?
There's a really simple pattern for this type of iterator, using closure scope to store a loop counter and a nested looper() function which runs the setTimeout() iterator. The looper() function actually iterates the loop count, so there is no need for a for or do/while construct. I use this pattern often, and it works really well.
EDIT: Modified the condition to check for loop > 1, not loop > 0, which logged Loop count: 0. This can be tweaked, and technically, the looper() here runs 16 times.
(function(){
var loop = 15;
var looper = function(){
console.log('Loop count: ' + loop);
if (loop > 1) {
loop--;
} else {
console.log('Loop end.');
return;
}
setTimeout(looper, 15000);
};
looper();
})();
http://jsfiddle.net/userdude/NV7HU/2
Use this function to make it easier to run:
function loopArr(arr, callback, time, infinite){
console.log('loop run');
var i=0,
total=arr.length-1;
var loop=function(){
// RUN CODE
console.log('loop arr['+i+']');
callback( arr[i] );
if (i < total ) {
i++;
} else { // LOOP END
console.log('loop end!');
if(!infinite) return;
i=0 //restart
}
setTimeout( loop, time);
}
loop()
}
To use this function execute this:
loopArr(arr, callback, time, infinite)
Where:
arr is the array we need to loop, it could be a jQuery selector
callback is the executed function with one argument returned which is the selected item
time is the timeout needed for delay
infinite is set true or false if we need the code to repeat itself forever
Example using animate.css :
var imgShowHide = function(elm){
var elm = $(elm); // select the item arr[i] via jQuery
elm.css('animation-duration','2s').show()
.addClass('animated bounceInRight')
.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
elm.removeClass('animated bounceInRight')
.addClass('animated bounceInLeft')
.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
elm.removeClass('animated bounceInLeft').hide()
})
});
}
// RUN
loopArr( $('#images > img'), imgShowHide, 4000, true);