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

問題は、パラメーターigetNewIP(i)常に 10 であることです。

再帰について少し読んだことがありますが、このコードを変更する方法がわからないため、i0..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)
}

これは、クロージャーを使用するときによくある既知の問題です。

問題は基本的に同じであるため、詳細については、このスレッドを参照してください: ループで関数を setTimeout に渡す: 常に最後の値?

これも良いリファレンスです: Javascript の悪名高い Loop issue?

より読みやすい構文については、次のようなこともできます。

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