简体   繁体   English

node.js回调获取变量的意外值

[英]node.js callback getting unexpected value for variable

I have a for loop, and inside it a variable is assigned with var. 我有一个for循环,在其中一个变量赋值为var。 Also inside the loop a method is called which requires a callback. 同样在循环内部调用一个需要回调的方法。 Inside the callback function I'm using the variable from the loop. 在回调函数内部,我正在使用循环中的变量。 I would expect that it's value, inside the callback function, would be the same as it was outside the callback during that iteration of the loop. 我希望它在回调函数中的值与在循环迭代期间回调之外的值相同。 However, it always seems to be the value from the last iteration of the loop. 但是,它似乎总是来自循环的最后一次迭代的值。

Am I misunderstanding scope in JavaScript, or is there something else wrong? 我误解了JavaScript中的范围,还是有其他错误?

The program in question here is a node.js app that will monitor a working directory for changes and restart the server when it finds one. 这里讨论的程序是一个node.js应用程序,它将监视工作目录以进行更改,并在找到服务器时重新启动服务器。 I'll include all of the code for the curious, but the important bit is the parse_file_list function. 我将包含好奇的所有代码,但重要的是parse_file_list函数。

var posix = require('posix');
var sys = require('sys');
var server;
var child_js_file = process.ARGV[2];
var current_dir = __filename.split('/');
current_dir = current_dir.slice(0, current_dir.length-1).join('/');

var start_server = function(){
    server = process.createChildProcess('node', [child_js_file]);
    server.addListener("output", function(data){sys.puts(data);});
};

var restart_server = function(){
    sys.puts('change discovered, restarting server');
    server.close();
    start_server();
};

var parse_file_list = function(dir, files){
    for (var i=0;i<files.length;i++){
        var file = dir+'/'+files[i];
        sys.puts('file assigned: '+file);
        posix.stat(file).addCallback(function(stats){
            sys.puts('stats returned: '+file);
            if (stats.isDirectory())
                posix.readdir(file).addCallback(function(files){
                    parse_file_list(file, files);
                });
            else if (stats.isFile())
                process.watchFile(file, restart_server);
        });
    }
};

posix.readdir(current_dir).addCallback(function(files){
    parse_file_list(current_dir, files);
});

start_server();

The output from this is: 这个输出是:

file assigned: /home/defrex/code/node/ejs.js
file assigned: /home/defrex/code/node/templates
file assigned: /home/defrex/code/node/web
file assigned: /home/defrex/code/node/server.js
file assigned: /home/defrex/code/node/settings.js
file assigned: /home/defrex/code/node/apps
file assigned: /home/defrex/code/node/dev_server.js
file assigned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js
stats returned: /home/defrex/code/node/main_urls.js

For those from the future: node.devserver.js 对于未来的人: node.devserver.js

This is perfectly normal behaviour. 这是完全正常的行为。 Your callbacks are executed at some later point (asynchronously) but still reference the scope your for loop was running in. All callback references to file will therefore have the last value it was set to. 您的回调在稍后的某个时间点执行(异步),但仍然引用您的for循环运行的范围。因此,对文件的所有回调引用都将具有它设置的最后一个值。

What you want to do is create a new function scope, assign the current value of file to a local variable and create the callback inside that scope. 您要做的是创建一个新的函数作用域,将文件的当前值分配给局部变量在该作用域内创建回调。

    for (var i=0;i<files.length;i++){
        var file = dir+'/'+files[i];
        (function() {
            var file_on_callback = file;
            sys.puts('file assigned: '+ file_on_callback);
            posix.stat(file_on_callback).addCallback(function(stats){
                sys.puts('stats returned: '+ file_on_callback);
                if (stats.isDirectory())
                    posix.readdir(file_on_callback).addCallback(function(files){
                        parse_file_list(file_on_callback, files);
                    });
                else if (stats.isFile())
                    process.watchFile(file_on_callback, restart_server);
            });
        })(); // This creates and executes a new function with its own scope.
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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