1

我有以下 Node.js 代码:

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

问题是参数i, intogetNewIP(i)总是 10!

我已经阅读了一些关于递归的内容,但我不知道如何修改此代码,使其i为 0..9 而并非总是 10。

提前谢谢了,

4

2 回答 2

3

这是闭包的问题...

试试这个:

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); // <-----
}
于 2013-06-20T12:37:25.243 回答
2

简单地说你的问题与此成正比:

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

为了解决这个问题,您可以将代码包装在一个新函数中:

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

这是人们在使用闭包时经常遇到的已知问题!

您可以参考此线程以获取更多信息,因为问题基本相同:Passing functions to setTimeout in a loop: always the last value?

这也是一个很好的参考: Javascript infamous Loop issue?

要获得更易读的语法,您还可以执行以下操作:

for(i = 0; i < 10; i++){
    with({i: i}){
        setTimeout(function(){ alert(i);}, 1000);
    }
}
于 2013-06-20T12:41:41.270 回答