Tag: javascript

The task is to execute a function with a callback multiple times but each time I want to pass my loop ‘item’ variable to the callback function.

Let’s consider the following code example.

for(varitem=0;item<3;item++){/* This function gets called immediately, however execCallback will not. Note that this function won't block the execution */setTimeout(callback,100);functioncallback(){/* Since setTimeout need 100 milesecond console.log will be executed only when 'for' loop is finished leaving as with item = 10 */console.log(item);}// This console.log will executed immidiatelyconsole.log('Item: %s',item)}

This is the code output

λnodecallback-args_02.jsItem:0Item:1Item:2333

We can see that item gets logged immediately 3 times but callback returned 100 ms later when the item was on its last value which is 3. How can we male callback aware of current loop iteration?

We can do that by cloning the value of ‘item’ variable into the scope of another function which can not be altered from higher level.

A closure is an expression (typically a function) that can have free variables together with an environment that binds those variables (that “closes” the expression).Since a nested function is a closure, this means that a nested function can “inherit” the arguments and variables of its containing function. In other words, the inner function contains the scope of the outer function. [1]

The following example demonstrate the concept of local and global scope

varglobalVar="I'm global var";functionmyFunc(){// This will create globalVar in local context of myFunc// which doesn't interfear with the global onevarglobalVar="I'm local var";returnglobalVar;}console.log('myFunc scope globalVar:',myFunc());console.log('Global scope globalVar:',globalVar);

Notice how value 2 gets saved inside of addTwo object scope. This might be used to solve our original callback problem.

Let’s wrap our setTimeout into another function. By doing so we will crate function closure and create new object with our ‘item’ value for every iteration of the loop.

for(varitem=0;item<3;item++){/* New objec created from callWraper every iteration of the loop it will preserve our item number for callback */functioncallWrapper(i){setTimeout(callback,100);functioncallback(){/* Since callback function is a child of callWrapper it will have access to its scope */console.log(i);}}callWrapper(item);// This console.log will executed immidiatelyconsole.log('Item: %s',item)}

Result

λnodecallback-with-args-example.jsItem:0Item:1Item:2012

Now we calling setTimer asynchronously and preserving the ‘item’ value to print it later to the console.