Domanda

Ho un ciclo, e al suo interno una variabile viene assegnato con var. Anche all'interno del ciclo viene chiamato un metodo che richiede un callback. All'interno della funzione di callback che sto utilizzando la variabile dal loop. Mi aspetto che il suo valore, all'interno della funzione di richiamata, sarebbe lo stesso come era fuori la richiamata durante tale iterazione del ciclo. Tuttavia, sembra sempre di essere il valore della ultima iterazione del ciclo.

Sono io malinteso portata in JavaScript, o c'è qualcosa che non va?

Il programma in questione: ecco un app node.js che controllerà una directory di lavoro per le modifiche e riavviare il server quando ne trova uno. Io includo tutto il codice per i curiosi, ma il bit importante è la funzione 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();

L'output di questo è:

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

Per quelli dal futuro: node.devserver.js

È stato utile?

Soluzione

Questo è perfettamente normale comportamento. I suoi callback vengono eseguiti in un momento successivo (in modo asincrono), ma ancora riferimento l'ambito tuo per ciclo era in esecuzione in. Tutti i riferimenti di callback per file sarà quindi avere l'ultimo valore è stato impostato.

Che cosa si vuole fare è creare un nuovo ambito di funzione, assegnare il valore corrente di file a una variabile locale e creare la richiamata all'interno di quella portata.

    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.
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top