1

I have this for loop in my node.js application:

for (var runNumber=1; runNumber<=numberOfRuns; runNumber++) {
  runNumberQueue.place(function(){
    versionRunningService.runMultiVersionJobs(
      queue, jobId, sVersion, jobType, runNumber, currentConfig, allJobsConfig, appDir, function(){
        runNumberQueue.next();
        currentIterationCount++;
        if (currentIterationCount === numberOfIterations) {
          callback();
        }
    });
  });
}

Is there somethingwrong with the structure of it? It seems to increment runNumber then execute the runNumberQueue.place function with runNumber 1, skip execution of runNumberQueue.place for runNumber 2 and execute again correctly for runNumber 3.

I wondered if it could be some asynch issue either but think that runNumberQueue.place would execute with runNumber 2 at some stage?

pac
  • 491
  • 1
  • 7
  • 30
  • 1
    What is `runNumberQueue`, especially the code for `next()`? Also, where is `numberOfIterations` defined and what does `callback()` do? – Yserbius Mar 27 '18 at 16:28
  • 1
    Add `var runNumberCopy = runNumber;` before `runNumberQueue.place` and use `runNumberCopy` instead. – Behrooz Mar 27 '18 at 16:37
  • runNumberQueue is a Queue object created with sync-queue package. next() moves to the next item in the queue. See https://www.npmjs.com/package/sync-queue @Behrooz, thanks I tried that and it seems to have resolved my issue. Is there a reason why this happened and is that a common whenusing for loops with node.js? – pac Mar 27 '18 at 20:24

1 Answers1

1

The way JavaScript works inside loops is that the variable defined inside the loop score (e.g., runNumber here) are bound to the same scope. So when you run an anonymous function inside the loop, it uses those variables bound to the loop scope, and not the function scope.

This is a common situation in JS loops. To avoid this, you can either define a secondary variable to capture the value of loop index variable or define an external function instead of the anonymous function.

A secondary variable:

for (var runNumber=1; runNumber<=numberOfRuns; runNumber++) {
  var runNumberCopy = runNumber;
  runNumberQueue.place(function(){
    versionRunningService.runMultiVersionJobs(
      queue, jobId, sVersion, jobType, runNumberCopy, currentConfig, allJobsConfig, appDir, function(){
        runNumberQueue.next();
        currentIterationCount++;
        if (currentIterationCount === numberOfIterations) {
          callback();
        }
    });
  });
}

An external function:

for (var runNumber=1; runNumber<=numberOfRuns; runNumber++) {
  placeRunNumberQueue(runNumber);
}

// this function can be defined elsewhere and passed all the required arguments
function placeRunNumberQueue(runNumber) {
  runNumberQueue.place(function(){
    versionRunningService.runMultiVersionJobs(
      queue, jobId, sVersion, jobType, runNumber, currentConfig, allJobsConfig, appDir, function(){
        runNumberQueue.next();
        currentIterationCount++;
        if (currentIterationCount === numberOfIterations) {
          callback();
        }
    });
  });
}

There is another post going over this issue in more details.

Behrooz
  • 2,181
  • 1
  • 16
  • 24