21

JavaScriptとnode.jsは初めてです。ディレクトリをループして、すべてのファイル統計(他のディレクトリではない)を配列に追加したいと思います。以下に示すように、forループが終了した後にコールバックが呼び出される可能性があるため、コードに問題があります。そのため、コールバックメソッドで「i」変数を使用しても機能しません。しかし、以下のスニペットが機能するように、コードはどのように見えるべきですか?それは閉鎖と関係がありますか?

手伝ってくれてありがとう!

    fs.readdir(SYNCDIR, function(err1, files) {
        var filesOnly = [];

        if(!err1) {

            for(var i = 0; i < files.length; i++) {

                var imgFilePath = SYNCDIR + '/' + files[i];
                fs.stat(imgFilePath, function(stat){

                    if (stat.isFile()){
                        filesOnly[i] = stat; // This will not be correct since the for-loop has finished
                    }
                });

            }
        }
    });
4

3 に答える 3

32

あなたはクロージャーを使用する必要があることについて正しいです。forループの内容を自己呼び出し関数でラップしてi、各反復の値を保持する必要があります。

fs.readdir(SYNCDIR, function(err1, files) {
    var filesOnly = [];

    if(!err1) {

        for(var i = 0; i < files.length; i++) {

            (function(i) {
                var imgFilePath = SYNCDIR + '/' + files[i];
                fs.stat(imgFilePath, function(stat){
                    if (stat.isFile()){
                        filesOnly[i] = stat;
                    }
                });
            })(i);

        }
    }
});
于 2011-09-01T10:55:05.107 に答える
10

1つの方法は、クロージャーを使用するようにループの内部を書き直すことです。

fs.readdir(SYNCDIR, function(err1, files) {
    var filesOnly = [];
    if(!err1) {
        for(var i = 0; i < files.length; i++) {
            (function(index) {
                var imgFilePath = SYNCDIR + '/' + files[index];
                fs.stat(imgFilePath, function(stat){
                    if (stat.isFile()){
                        filesOnly[index] = stat;
                    }
                });
            })(i);
        }
    }
});

Array.prototype.forEachを使用して同じことを実現する、見栄えの良い例:

fs.readdir(SYNCDIR, function(err1, files) {
    var filesOnly = [];
    if(!err1) {
        files.forEach(function(file, i) {
            var imgFilePath = SYNCDIR + '/' + file;
            fs.stat(imgFilePath, function(stat){
                if (stat.isFile()){
                    filesOnly[i] = stat;
                }
            });
        });
    }
});
于 2011-09-01T10:58:28.450 に答える
0

または、新しいスレッドモジュール(https://github.com/robtweed/Q-Oper8)を使用すると、スレッドの子プロセス内で標準の同期コーディングを使用するだけで、1人のユーザーのリクエストのみを処理できるため、これらすべてをはるかに簡単に行うことができます。一度に。

非同期ロジックとネストされたコールバックに別れを告げます!

于 2011-09-01T12:17:14.003 に答える