I am new to node.js and very inexpert when it comes to async processing.
I have a list of functions in an array, which I need to call asynchronously when a message arrives. I planned to use process.nextTick
to schedule the calls. This is my (simplified) code:
// These are example message handlers
// All have to be called on every message
function fn1( msg ) { console.log( "fn1: " + msg ) };
function fn2( msg ) { console.log( "fn2: " + msg ) };
function fn3( msg ) { console.log( "fn3: " + msg ) };
// the functions to be called are saved in a list
var fns = [ fn1, fn2, fn3 ];
// function to schedule async callbacks to every
// function in the list.
function multicall( msg ){
// schedule the call back to each function
for( var ix = 0; ix < fns.length; ix++ ){
var fn = fns[ix];
process.nextTick( function() {
// call the nth function with the message
fn( msg );
}
);
}
}
// now make the call to schedule callbacks
console.log( "start" );
multicall( "information" );
console.log( "end" );
The calls are queued as expected, but the problem is that when the calls are made, they are all to the last function, instead of one call to each function. Presumably this is because the call to fn( msg )
actually references the value of the variable fn
at the time of the call, not at the time that the function is was scheduled. The calls are therefore all made to the last function in the list:
S:\test>node asyncTest
start
end
fn3: information
fn3: information
fn3: information
I have tried various approaches but can't seem to get round this problem of the difference between the function referenced when the call is scheduled, and the function referenced when the call is executed.
EDIT - - - -
Although I accept that @jishi's answer below is better, I inadvertently found another answer to this problem, which is to use let fn = fns[ix];
instead of var fn = fns[ix];
. When using let
, the for
loop creates a completely new variable on each iteration, so the value set in one cycle is not overwritten by the value set in the next cycle. I hadn't previously understood that the scope of a let
variable is limited to each specific execution of the code block, not just by the static lexical structure of the code.