Подтвердить что ты не робот

Для цикла и асинхронного обратного вызова в node.js?

Я новичок в JavaScript и node.js. Я хочу прокрутить каталог и добавить в файл весь файл stat (не другие каталоги). Как вы видите ниже, проблема связана с моим кодом, так как обратный вызов, вероятно, будет вызван после завершения цикла 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
                    }
                });

            }
        }
    });
4b9b3361

Ответ 1

Вы правы в том, что нужно использовать закрытие. Вы должны обернуть содержимое цикла 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);

        }
    }
});

Ответ 2

Один из способов - переписать внутренности цикла для использования замыкания:

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

Ответ 3

В качестве альтернативы используйте новый модуль потоков (https://github.com/robtweed/Q-Oper8), а затем вы можете сделать все это намного проще, используя стандартное синхронное кодирование в пределах потоки дочерних процессов, поскольку они обрабатывают только один запрос пользователя за раз.

До свидания с асинхронной логикой и вложенными обратными вызовами!