简体   繁体   中英

Node.js — please help me with recursion

I have the following Node.js code:

var exec=require('child_process').exec;

var base_ctrl_port=8118;
var base_data_port=9050;
var nConns=10;

watchdogCycle();
setInterval(watchdogCycle, 60000);   //check health every 60 seconds...

function watchdogCycle(){
        console.log("\n");
        for(var i=0;i<nConns;i++){
                var data_port=base_data_port+i;
                data_port=data_port+"";
                var curl=exec('curl -b -s --socks5 localhost:'+data_port+' http://ifconfig.me',{timeout:10000},
                function(err,stdout,stderr){
                        console.log(stdout);
                        if(err!=null){
                                getNewIP(i);   //PROBLEM: i is always 10!!!
                        }
                });
        }
}

function getNewIP(offset){
        console.log("Getting new IP address for tor data port: "+(base_data_port+offset+0)+"...");
        var ctrl_port=base_ctrl_port+offset;
        var nc=exec('(echo AUTHENTICATE \'\"xxxxxx\"\'; echo SIGNAL NEWNYM; echo quit) | nc localhost '+ctrl_port,
        function(err,stdout,stderr){
                console.log(stdout);
        });
}

The problem is that the parameter, i , into getNewIP(i) is always 10!

I've read up a bit about recursion, but I don't know how to modify this code so that i is 0..9 and not always 10.

Many thanks in advance,

This is a problem with closures...

Try this:

for(var i=0;i<nConns;i++){
    var data_port=base_data_port+i;
    data_port=data_port+"";
    (function (i){ // <-----
        var curl=exec('curl -b -s --socks5 localhost:'+data_port+' http://ifconfig.me',{timeout:10000},
            function(err,stdout,stderr){
                console.log(stdout);
                if(err!=null){
                    getNewIP(i);   //PROBLEM: i is always 10!!!
                }
            });
    })(i); // <-----
}

Simply saying your problem is proportional to this:

for(i = 0; i < 10; i++){
    setTimeout(function(){ alert(i);}, 1000);
}

In order to solve the problem, you can do wrap your code in a new function:

for(i = 0; i < 10; i++){
    (function(otherI){
        setTimeout(function(){ alert(otherI); }, 1000);
    })(i)
}

This is a known problem people often have when using closures!

You can refer to this thread for more information, as the problems are basically the same: Passing functions to setTimeout in a loop: always the last value?

This is also a good reference: Javascript infamous Loop issue?

For a more readable syntax, you can also do something like:

for(i = 0; i < 10; i++){
    with({i: i}){
        setTimeout(function(){ alert(i);}, 1000);
    }
}

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