2009-12-09 48 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. 
    }