I have a function:
setInterval(function () {
var counter = 0;
(function() {
counter = counter + 1;
console.log(counter);
})(counter)
}, 1000)
Why does not it increment the counter? (instead, it logs 1's). How to make it log ascending numbers? (1, 2, 3, ....)
You could use a function which returns a function as closure over counter.
setInterval(function(counter) {
return function() {
console.log(++counter);
};
}(0), 1000);
You are passing an argument to your anonymous function, but you aren't assigning that argument to a variable. You forgot to put the arguments in the function definition.
You are creating new variables with every iteration instead of sharing the variable between them. You need to turn your logic inside out.
(function(closed_over_counter) {
setInterval(function() {
closed_over_counter++;
console.log(closed_over_counter);
}, 1000);
})(0);
Since you are using an IIFE instead of a function you can call multiple times, this is pretty pointless. You might as well just declare the variable inside the closure.
(function() {
var counter = 0;
setInterval(function() {
counter++;
console.log(counter);
}, 1000);
})();
Obscured version of Nina Scholz's answer with arrow functions:
setInterval(((counter) => () => console.log(++counter))(0), 1000);
Related
I would like to know if there is a way to use setTimeout recursive implements with an arrow function, in order to use this (refers to my class attribute for example) inside. Indeed, this = undefined when i declare my setTimeout with a normal function
I got :
public currentIndex: number = 0;
setTimeout(function run(){
this.currentIndex++;
console.log(this.currentIndex); // returns undefined
setTimeout(run, 1000);
}, 1000)
Instead of :
setTimeout(() => {
this.currentIndex++;
console.log(this.currentIndex) // returns currentIndex value
setTimeout( ?? , 1000) // What should i put instead of '??' ?
}, 1000)
You could bind this first and then use this function for all calls.
function run(reference) {
this.currentIndex++;
console.log(this.currentIndex); // returns undefined
setTimeout(reference, 1000, reference);
}
const runThis = run.bind(thisReference);
setTimeout(runThis, 1000, runThis);
Its because arrow function does not create new context inside arrow function body but normal function does. So this in arrow function refers to parent scope context but this in normal function refers to its own context.
This will create setTimeouts recursively
let currentIndex = 0;
const run = () => {
setTimeout(() => {
currentIndex++;
console.log(currentIndex);
run();
}, 1000);
}
run();
but better approach may be (I don't know your use case, so it is just maybe) to use setInterval()
let currentIndex = 0;
const interval = setInterval(() => {
currentIndex++;
console.log(currentIndex);
// stop interval
if (currentIndex >= 10) {
clearInterval(interval);
}
}, 1000);
Probably the easiest way is to extract the arrow function into its own variable:
const run = () => {
this.currentIndex++;
console.log(this.currentIndex);
setTimeout(run, 1000);
};
setTimeout(run, 1000);
Though in this particular example you could simplify it even more using setInterval instead of setTimeout, avoiding the second setTimeout call entirely.
I have a function called "showCustomer" that get number between 1-5 and return something.
I want to use setInterval, to run this function every 5 second but with another number.
Its not working, i don't understand why its not working to me. here is the code.
setInterval(function () {
var i = 1;
showCustomer(i);
i++;
}, 5000);
Just move the declaration of variable i before the setInterval() call:
var i = 1;
setInterval(function () {
showCustomer(i);
i++;
}, 5000);
The anonymous function you've set as a callback for setInterval gets called every 5 seconds in your code. In every call, you're setting i to 1 which resets it every time.
Moving i outside the setInterval callback makes it persist the the current value.
Every time you use var, you redeclare the value of that variable. So you only should declare the counter one time.
Every time that the browser calls the callback showCustomer the if statement evaluates if the browser should make a new call.
clearInvertal() it's the method to stop the setInterval() method.
var id = 1;
var show5times = window.setInterval(showCustomer, 5000);
function showCustomer() {
alert(id);
id++;
if(id > 5) {
window.clearInterval(show5times);
}
}
I am creating two function name call and call2 and putting this two functions in array x. In another function called timer i am trying to call this function every 2 seconds. But its giving error expected an assigment or function call instead show and expression.
And also i dont want this functions to run when i create an array.
this my code http://jsbin.com/IMiVadE/2/
function call(name)
{
console.log("Hello " + name);
}
function call2()
{
console.log("Hello world");
}
var x = [call("Nakib"), call2()];
var i = 0;
function timer(x, i)
{
x[i];
i++;
if(i<x.length)
window.setTimeout(timer(x, i), 2000);
}
timer(x, i);
You have some mistakes in your code:
call2() calls the function. Correct: call2 is the reference to the function.
x[i] accesses the value (the function reference). You need x[i]() to execute the function.
Here is your code working: http://jsbin.com/IMiVadE/6/edit
sayHello(name) is a function that generates new functions that output a specific "Hello ..." text.
function sayHello(name)
{
return function () {
console.log("Hello " + name);
}
}
function timer(x, i)
{
x[i]();
if (i < x.length - 1) {
setTimeout(function () {
timer(x, i + 1);
}, 2000);
}
}
var x = [sayHello("Nakib"), sayHello("world")];
setTimeout(function () {
timer(x, 0);
}, 2000);
setTimeout needs a function without parameter. So you can wrap the recursive call to timer in an anonymous function to fix that:
window.setTimeout(function(){timer(x, i)}, 2000);
Also, the first line in your timer function, consisting only of x[i];, is useless, although it probably isn't the cause of your problem.
The setTimeout function takes a function as a parameter, you are executing the timer function before it is passed and since timer doesn't return anything, undefined is being passed to the timeout;
window.setTimeout(timer(x, i), 2000); // is the same as...
window.setTimeout(undefined, 2000);
It should be;
window.setTimeout(function() { timer(x, i) }, 2000); // or...
window.setTimeout(timer.bind(this, x, i), 2000);
I'm not sure if this is intentional, but you are doing the same thing with your array;
var x = [call("Nakib"), call2()];
This will execute the functions and their results will be stored in the array. Is this what you want?
If I have a function like so:
function x()
{
animate(a, 2000);
animate(b, 3000);
animate(c, 4000);
}
Where - a, b & c - are variables representing elements on the page, and the number is a parameter passed to an animate() function that uses it as a duration value for a timeout, like so:
function animate(src, dur)
{
setTimeout(function() {
src.style.opacity = 1;
}, dur);
}
Everything so far is fine, but if I want the ability to break out of the animation loop, how do I go about it? Will clearTimeout() be what I'm looking for?
Variables that have been assigned a timeout, may be passed to the clearTimeout function, which will cease the function. You can store these variables in an array and easily clear all timeouts by iterating this array and passing the timeout to the clearTimeout function.
var timeouts = [];
/* Save timeouts into a variable and push to an array */
function animate(src, dur)
{
var timeout = setTimeout(function() {
src.style.opacity = 1;
}, dur);
timeouts.push(timeout);
}
/** Clear all timeouts**/
function clearTimeouts(){
for(var i = 0; i < timeouts.length; i++){
clearTimeout(timeouts[i]);
}
}
//Create timeouts
x();
//Invoke clearTimeouts
clearTimeouts();
Yes, clearTimeout() is the right way to go:
function animate(src, dur)
{
return setTimeout(function() {
src.style.opacity = 1;
}, dur);
}
And save returned identifier:
function x()
{
var aId = animate(a, 2000);
var bId = animate(b, 3000);
var cId = animate(c, 4000);
}
Later you simply call clearTimeout(aId) or whichever you desire. BTW there is no loop in your code, setTimeout() executes only once, as opoosed to setInterval().
The issue was my array was [[][][]] instead of [[]] : /
This is my Script
function loopobject(array) {
var me = this;
this.array = array;
this.loop = function() {
counter = 0;
while(array.length > counter) {
window[array[counter]]('arg1', 'arg2');
counter++;
}
setTimeout(function(){ me.loop() }, 100);
}
}
var loopinstant = new loopobject(array);
window.onload = loopinstant.loop();
The problem arises after the first iteration. I don't know exactly the problem but I'm wondering if its due to the fact this is inside an object, and once the function is recreated it doesn't remember the array?
Don't pass a string to setTimeout.
Passing a string to setTimeout causes it to be evaled in global scope.
In addition to being needlessly slow, that means that it won't see your local variables, including the loop variable.
Instead, you should pass a function itself to setTimeout:
setTimeout(function() { loop(array); }, 100);
Also, the loopobject doesn't actually have a loop property that you can call later.
To make a property, change it to this.loop = function(...) { ... }.
Note that the setTimeout callback won't be called with the correct this.
You'll also need to save a copy of this in a local variable.
Finally, your window.onload code will call loop, then assign the result to onload.
Correcting these issues, your code turns into
function loopobject(){
var me = this;
this.loop = function(array){
counter = 0;
while(array.length > counter){
window[array[counter]]('arg1', 'arg2');
counter++;
}
setTimeout(function() { me.loop(array); }, 100);
};
}
var loopinstant = new loopobject();
window.onload = function() { loopinstant.loop(array); };
Replace
setTimeout("loop()", 100);
with
setTimeout(function() { loop(array); }, 100);