2016-06-26 20 views
1

私はNode.jsを使い慣れています私はNode.jsを勉強しているうちに、私は非同期/同期の事柄に関連する点に固執しました。他の例からの非同期関数とコールバックのロジックを理解しています。しかし、私は以下の例を理解していませんでした。私はそれを引用しました:http://code-maven.com/list-content-of-directory-with-nodejsコールバック関数forループ内のコールバック関数

なぜ以下のコードが正しく動作しないのですか?著者はfs.stat()メソッドの最初のパラメータから原因があると言います。これを行う正しい方法は、最後の2つの作業例に示されています。私は、作業例と非作業例の違いと、最初の例が正しく動作せず、最後の2つの例が適切に機能する理由を理解していません。

var fs = require('fs'); 

if (process.argv.length <= 2) { 
    console.log("Usage: " + __filename + " path/to/directory"); 
    process.exit(-1); 
} 

var path = process.argv[2]; 

fs.readdir(path, function(err, items) { 
    for (var i=0; i<items.length; i++) { 
     var file = path + '/' + items[i]; 
     console.log("Start: " + file); 

     fs.stat(file, function(err, stats) { 
      console.log(file); 
      console.log(stats["size"]); 
     }); 
    } 
}); 

出力は次のようになります。

$ node examples/node/list_dir_direct.js ~/work/code-maven.com/examples/ 

Start: /home/gabor/work/code-maven.com/examples//blocking-read-file.js 
Start: /home/gabor/work/code-maven.com/examples//node_hello_world.js 
Start: /home/gabor/work/code-maven.com/examples//node_hello_world_port.js 
Start: /home/gabor/work/code-maven.com/examples//non-blocking-read-file.js 
Start: /home/gabor/work/code-maven.com/examples//process_exit.js 
Start: /home/gabor/work/code-maven.com/examples//raw_command_line_arguments.js 
Start: /home/gabor/work/code-maven.com/examples//read_dir.js 
Start: /home/gabor/work/code-maven.com/examples//stats.js 

/home/gabor/work/code-maven.com/examples//stats.js 
97 
/home/gabor/work/code-maven.com/examples//stats.js 
243 
/home/gabor/work/code-maven.com/examples//stats.js 
270 
/home/gabor/work/code-maven.com/examples//stats.js 
151 
/home/gabor/work/code-maven.com/examples//stats.js 
18 
/home/gabor/work/code-maven.com/examples//stats.js 
324 
/home/gabor/work/code-maven.com/examples//stats.js 
27 
/home/gabor/work/code-maven.com/examples//stats.js 
1382 

デバッグプリントアウトが期待通りの名前を印刷したが、その後fs.statのコールバックの内側()私たちは同じファイル名をプリントアウトしておきます。我々はfs.statを()と呼ばれるように、これらは同じ順序で印刷されたため、サイズがファイル名と一致するように見える

$ ls -l ~/work/code-maven.com/examples/ 
total 64 
-rw-r--r-- 1 gabor staff 97 Jan 29 14:26 blocking-read-file.js 
-rw-r--r-- 1 gabor staff 243 Jan 27 12:34 node_hello_world.js 
-rw-r--r-- 1 gabor staff 270 Jan 27 12:34 node_hello_world_port.js 
-rw-r--r-- 1 gabor staff 151 Jan 29 14:26 non-blocking-read-file.js 
-rw-r--r-- 1 gabor staff 18 Jan 31 08:24 process_exit.js 
-rw-r--r-- 1 gabor staff 27 Jan 29 14:54 raw_command_line_arguments.js 
-rw-r--r-- 1 gabor staff 324 Jan 31 15:26 read_dir.js 
-rw-r--r-- 1 gabor staff 1382 Jan 31 10:45 stats.js 

の出力に結果を比較しますが、何らかの理由でファイルの変数の内容でしたコールバックごとに同じです。これは、ファイル変数が単純なグローバル変数(コールバックの観点から)であり、最初のコールバックが実行された時点で、ファイル変数にすでにディレクトリの最後のエントリが割り当てられているためです。

以下のコードは正しく動作します。

var fs = require('fs'); 

if (process.argv.length <= 2) { 
    console.log("Usage: " + __filename + " path/to/directory"); 
    process.exit(-1); 
} 

var path = process.argv[2]; 

fs.readdir(path, function(err, items) { 
    for (var i=0; i<items.length; i++) { 
     var file = path + '/' + items[i]; 

     console.log("Start: " + file); 
     fs.stat(file, generate_callback(file)); 
    } 
}); 

function generate_callback(file) { 
    return function(err, stats) { 
      console.log(file); 
      console.log(stats["size"]); 
     } 
}; 

また、以下のコードも正しく動作します。

var fs = require('fs'); 

if (process.argv.length <= 2) { 
    console.log("Usage: " + __filename + " path/to/directory"); 
    process.exit(-1); 
} 

var path = process.argv[2]; 

fs.readdir(path, function(err, items) { 
    for (var i=0; i<items.length; i++) { 
     var file = path + '/' + items[i]; 

     console.log("Start: " + file); 
     fs.stat(file, function(f) { 
      return function(err, stats) { 
       console.log(f); 
       console.log(stats["size"]); 
      } 
     }(file)); 
    } 
}); 
+0

これは、普通のforループの代わりに 'items.forEach()'を使うのに特に便利です。 – Alnitak

答えて

0

最初の例では、参照渡しが機能します。ファイル変数は参照によって渡されるため、コールバック関数は変数fileの最後の値をとり、正しく機能しません。 2番目と3番目の例では、値渡しが機能します。ファイル変数は値によって渡されるので、コールバック関数は各ファイルの名前を正しく取ります。

関連する問題