2009-12-09 2 views
7

for 루프가 있으며 그 안에 변수가 var로 할당되어 있습니다. 또한 루프 내부에서 콜백이 필요한 메소드가 호출됩니다. 콜백 함수에서 루프의 변수를 사용하고 있습니다. 콜백 함수 내부의 값은 루프의 반복 동안 콜백 외부와 같을 것이라고 기대합니다. 그러나 항상 루프의 마지막 반복에서 값을 것 같습니다.node.js 변수에 대해 예기치 않은 값을 가져 오는 콜백

JavaScript에서 범위를 잘못 이해하고 있습니까? 아니면 다른 점이 있습니까?

여기서 문제가되는 프로그램은 작업 디렉토리에서 변경 사항을 모니터링하고 서버가 발견되면 다시 시작하는 node.js 응용 프로그램입니다. 호기심에 대한 모든 코드를 포함 하겠지만, 중요한 것은 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(); 

이의 출력은 : 미래에서 사람들을 위해

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 

:node.devserver.js

답변

15

이 완벽하게 정상적인 동작입니다. 콜백은 나중에 (비동기 적으로) 실행되지만 은 루프가 실행 중이므로 루프가 실행되고 있습니다. 따라서 파일에 대한 모든 콜백 참조는 마지막 값으로 설정됩니다. 당신이 원하는 무엇

은 새로운 기능의 범위를 만들 로컬 변수 그 범위 내에서 콜백을 만들 수 파일의 현재 값을 할당한다.

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. 
    } 
관련 문제