Monthly Archives: March 2014

What are anonymous self-invoking functions in JavaScript?

Have you ever been confused by something like this?

(function() { 
    console.log('hello world');
})();

This function invokes itself after it has been declared, meaning it calls itself right after you have declared it. All we are doing is wrapping the function into parentheses and then call it like you would call any function with (). Think of it this way:

(function)();

Some people use .call() (which does exactly the same), because the other syntax can be confusing for people who have just started with JavaScript:

(function).call();

To finish this post off, let us have a look at a real world example of an anonymous, self-invoking function:

var list = (function() {
    // declare variables that cannot be used outside of the function scope
    var x = 10;
    var y = 20;

    return [x, y];
})();

// correctly logs [10, 20]
console.log(list);

// throws a reference error
console.log(x);

for-Loop with Delay in JavaScript

Update November 2016:

While this post is still valid for ES5, I wanted to point out that there is now an easier method using async/await in the latest TypeScript 2.1.0 release. You can use this feature natively in the latest Node version, but TypeScript now allows you to compile async/await to ES5 for browsers.

You should still read the original post, especially if you found this blog entry while googling a similar problem.

const delay = (amount: number) => {
  return new Promise((resolve) => {
    setTimeout(resolve, amount);
  });
};

async function loop() {
  for (let i = 0; i < 50; i++) {
    console.log(i);
    await delay(100);
  }
}

loop();

Original Post

I've had multiple JavaScript beginners ask me this how they can create a for-loop with delay. This code is what most have come up with (for quick readers: not what you are looking for!):

for (var index = 1; index < 50; index++) {
    setTimeout(function() {
        console.log(index);
    }, 100);    
}

Now this prints "50" fifty times, because a for-loop is synchronous while setTimout is asynchronous. This means that the for-loop is finished very fast and has started 50 setTimeouts. After 100ms all of those setTimeout functions will fire together, therefore printing "50" fifty times. Note that the var-keyword binds variables to the function scope, not the current block scope like in other languages.

In order to create a for-loop with actual delay - in our case printing a number, waiting 100ms and printing the next number - you need to create a self-invoking, recursive function. Don't worry, it's not that hard.

var maxLoops = 50;
var counter = 0;

(function next() {
    if (counter++ > maxLoops) return;

    setTimeout(function() {
        console.log(counter);
        next();
    }, 100);
})();

Here we declare two variables, maxLoops and counter. These are for keeping track of how many times the function has called itself. Afterwards we create the function "next", put it in brackets and call it immediately. This is why it's called a self-invoking function.

The if-statement does two things. First of all it counts up our counter variable using the ++ operator. It also returns the function if it has been called 50 times, therefore stopping the loop.

The last part is the most important one. We create our setTimeout function and then call next() after the number has been printed. And that's how you create a for-loop with delay in JavaScript.

Here is an even shorter, but harder to understand solution:

(function next(counter, maxLoops) {
    // break if maxLoops has been reached
    if (counter++ > maxLoops) return;

    setTimeout(function() {
        console.log(counter);

        // call next() recursively
        next(counter, maxLoops);
    }, 100);
})(0, 50);