Question

I ai une boucle, et à l'intérieur d'une variable est affectée par var. Aussi à l'intérieur de la boucle d'une méthode est appelée ce qui nécessite un rappel. Dans la fonction de rappel que je utilise la variable de la boucle. Je pense que sa valeur, dans la fonction de rappel, serait le même que celui en dehors du rappel lors de cette itération de la boucle. Cependant, il semble toujours être la valeur de la dernière itération de la boucle .

Est-ce que je comprends mal la portée en JavaScript, ou est-il quelque chose d'autre mal?

Le programme en question est une application Node.js ici qui surveillera un répertoire de travail pour les changements et redémarrez le serveur quand il en trouve un. Je vais inclure tout le code pour les curieux, mais le bit important est la fonction 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();

La sortie de c'est:

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

Pour ceux de l'avenir: node.devserver.js

Était-ce utile?

La solution

Ce comportement est parfaitement normal. Vos callbacks sont exécutés à un moment plus tard (de façon asynchrone), mais toujours référence la portée de votre pour boucle est en cours d'exécution dans. Toutes les références de rappel à fichier ont donc la dernière valeur était mettre à.

Qu'est-ce que vous voulez faire est de créer un nouveau champ d'application de fonction, attribuer la valeur actuelle de fichier à une variable locale et créer la fonction de rappel dans ce champ.

    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.
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top