1

Can someone please explain me why the below code prints "arg1 0" while I expect it to print "arg1 hi". Is it due to the lexical scope?

runIt();

function localScoped(arg1, callback) {
  console.log('arg1', arg1);
  callback();
}

function runIt() {

   var myValue = 0;
   async.eachLimit(["hi"], 1,
      function launchOneVar(clientCode, doneLaunchOneVar) {

          async.waterfall([
              function (myCallback) {
                  myValue = clientCode;
                  myCallback();
              },
              async.apply(localScoped, myValue)
          ], function (err, result) {
              console.log(myValue);
              doneLaunchOneVar(null, result);
          });
      },
     function finishing(err) {
     }
  );

}
rohit12sh
  • 827
  • 2
  • 11
  • 24
  • you need to understand how javascript code works, in `async.apply(localScoped, myValue)` value of `myValue` is still 0 because it will be called before `myValue = clientCode;` move your code `async.apply` into `function (myCallback) {` block – Chetan Ameta Nov 09 '15 at 03:35
  • `async.apply` is in waterfall flow. It cannot be called until first function completes. That's why I asked it is related to the lexical scope. Can please give me more details? I can rewrite the code to fix the problem, but I would like to know the internals. – rohit12sh Nov 09 '15 at 03:46
  • 1
    see my answer, use `async.apply(localScoped)` instead of `async.apply(localScoped, myValue)` – Chetan Ameta Nov 09 '15 at 04:50
  • Your `apply` create a closure with old myValue, before waterfall start to run. – vp_arth Nov 09 '15 at 05:02

2 Answers2

1

Waterfall is just a function.
There is not any magic here.
Any function in Javascript must evaluate its arguments before call.

So, async.apply(localScoped, myValue) evaluates before async.waterfall and closured old myValue's value (0);

You can pass it through waterfall:

function (myCallback) {
  myValue = clientCode;
  myCallback(null , myValue);
},
async.apply(localScoped);

Or write a wrapper function, like:

function(next) {
  localScoped(myValue, next);
}
vp_arth
  • 14,461
  • 4
  • 37
  • 66
0

try below solution:

runIt();

function localScoped(arg1, callback) {
  console.log('arg1', arg1);
  callback();
}

function runIt() {
   var myValue = 0;
   async.eachLimit(["hi"], 1,
      function launchOneVar(clientCode, doneLaunchOneVar) {
        //console.log(clientCode);
          async.waterfall([

              function (myCallback) {
                  myValue = clientCode;
                  myCallback(null , myValue);
              },
              async.apply(localScoped)

          ], function (err, result) {
              console.log('last - '+myValue);
              doneLaunchOneVar(null, result);
          });
      },
     function finishing(err) {
     }
  );
}

how water fall works: .

Runs a list of async tasks, passing the results of each into the next one.

Runs an array of functions in series, each passing their results to the next in the array. However, if any of the functions pass an error to the callback, the next function is not executed and the main callback is immediately called with the error.

For more detail have a look at: https://www.npmjs.com/package/async-waterfall

Chetan Ameta
  • 7,696
  • 3
  • 29
  • 44