2016-06-26 12 views
1

Ich bin neu bei Node.js. Während ich Node.js studiere, steckte ich an einem Punkt, der mit asynchronem/synchronem Ding zusammenhing. Ich verstehe die Logik von asynchronen Funktionen und Callbacks aus anderen Beispielen. Allerdings habe ich das folgende Beispiel nicht verstanden. Ich zitierte es von: http://code-maven.com/list-content-of-directory-with-nodejsCallback-Funktion in For-Schleife in Callback-Funktion

Warum funktioniert der folgende Code nicht richtig? Der Autor sagt, dass es vom ersten Parameter der fs.stat() Methode verursacht. Die korrekte Vorgehensweise wird in den letzten beiden Arbeitsbeispielen gezeigt. Ich verstehe den Unterschied zwischen den funktionierenden und nicht funktionierenden Beispielen nicht und warum das erste Beispiel nicht ordnungsgemäß funktioniert und die letzten beiden Beispiele ordnungsgemäß funktionieren.

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

Der Ausgang ist:

$ 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 

Fehlerbeseitigungs Ausdruck gedruckt, die Namen wie erwartet, aber dann innerhalb des Rückrufs von fs.stat() halten wir die gleichen Dateinamen auszudrucken. die Ergebnisse an den Ausgang des Vergleichens

$ 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 

Die Größen erscheinen die Dateinamen übereinstimmen, da diese in der gleichen Reihenfolge gedruckt wurden, wie wir fs.stat genannt(), aber aus irgendeinem Grund der Inhalt der Datei Variable war das gleiche für jeden Rückruf. Dies geschieht, weil die Dateivariable nur eine einfache globale Variable ist (aus der Sicht des Callbacks) und zu dem Zeitpunkt, zu dem der erste Callback ausgeführt wurde, wurde der Dateivariable bereits der letzte Eintrag im Verzeichnis zugewiesen.

Der folgende Code funktioniert ordnungsgemäß.

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

Auch der folgende Code funktioniert auch richtig.

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

Dies ist ein besonders guter Anwendungsfall für die Verwendung von 'items.forEach()' anstelle einer einfachen 'for'-Schleife – Alnitak

Antwort

0

Im ersten Beispiel funktioniert Pass-by-Reference. Die Dateivariable wird als Referenz übergeben, daher nimmt die Callback-Funktion den letzten Wert der Dateivariable und funktioniert nicht korrekt. Im zweiten und dritten Beispiel funktioniert Pass-by-Value. Die Dateivariable wird als Wert übergeben, daher nimmt die Callback-Funktion den Namen jeder Datei richtig an.