Bryan Bryan - 7 months ago 25
Javascript Question

NodeJS callback in a for-loop value is the same

I was cleaning up my code and ran into a little trouble with callbacks, specifically getting the correct values to output when a callback is called. Could some explain to me why the following code spits out something that I'm not expecting and a possible solution without having to put in another parameter of i to the run() function, or is passing in i to know my index upon calling the callback the only way to do this?

for (var i in dls) {
run(dls[i][0], dls[i][1], function(isTrue){
if (isTrue) {
// Do true stuff here
} else {
console.log("Value is: " + dls[i][3])
}
});
}


Calling run() actually has the correct inputs inside, but upon that function calling the callback and going into the else statement, dls[i][3] spits out the same value i times.

I've tried putting different scopes around (run()) and such but to no avail and can't seem to wrap my head around this.

Thanks

EDIT:

If I wanted to split it up into a separate function, how would I do it?

var run = function(cb){
setTimeout(function() {
cb(false)
}, 3000);
}

for (var i in dls) {
run(dls[i][0], dls[i][1], (function(index) {
return extraction
})(i));
}

function extraction(isTrue){
if (isTrue) {
// stuff
} else {
console.log("Nothing changed in " + dls[i][3])
}
}


Here dls[i][3] is still incorrect and prints the same value 3 times.

Answer

You have fallen into the traditional "loop trap"

When it comes time for your callback to run i is now a different value.

What you can do is cache that value in another wrapper function:

for (var i in dls) {
    run(dls[i][0], dls[i][1], (function (currentIndex) { 
        return function(isTrue){
            if (isTrue) {
                // Do true stuff here
            } else {
                console.log("Value is: " + dls[currentIndex][3])
            }
        };
    })(i));
}