简体   繁体   中英

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.

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));
}

In regards to the edit / second question, assuming this is what you wanted to do:

// note that I changed the function signature of `run`
var run = function(val1, val2, cb) {
    setTimeout(function() {
        cb(false);
    }, 3000);
};

// note the `wrapper` here
for (var i in dls) {
    run(dls[i][0], dls[i][1], wrapper(i));
}

// this is the same as what the IIFE is doing,
// just with an external function instead
function wrapper(scopedIndex) {

    // return a function to be used as the callback for `run`
    return function extraction(isTrue) {
        if (isTrue) {
            // stuff
        }
        else {
            // use the scoped index here
            console.log("Nothing changed in " + dls[scopedIndex][3]);
        }
    }
}

Take a look at function makeExitCallback(i) in the other linked question , as well. It directly relates to what's going on here.

You should post what's in dls as well, just to make it easier to run your snippets locally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM