Асинхронное чтение и кэширование нескольких файлов в nodejs - PullRequest
4 голосов
/ 08 марта 2012

У меня есть массив, который хранит URL нескольких файлов. Например:

var files = ['1.html', '2.html', '3.html'];

Мне нужно прочитать их асинхронно и сохранить в объекте с именем cache (cache = {}). Для этого я использовал код:

for(var i = 0; i < files.length; i++){
    require('fs').readFile(files[i], 'utf8', function (error,data) {
        cache[files[i]]=data;
    });
}

В итоге получаю результат:

cache = { undefined : 'File 3 content' }

Я понимаю, что readFile действует после завершения цикла и теряет свою область видимости. Есть ли способ исправить этот или другой метод чтения файлов из массива и кэширования их?

Ответы [ 2 ]

16 голосов
/ 08 марта 2012

Когда ваш обратный вызов на readFile выполняется, цикл for уже завершится. Таким образом, i будет files.length, а files[i] будет undefined. Чтобы смягчить это, вам нужно обернуть переменные в замыкание. Самый простой способ сделать это - создать функцию, которая выполняет ваш readFile вызов, и вызывать ее в цикле:

function read(file) {
    require('fs').readFile(file, 'utf8', function (error,data) {
        cache[file]=data;
    });
}

for(var i = 0; i < files.length; i++){
    read(files[i]);
}

Для еще лучшего контроля выполнения, вы можете посмотреть async :

function readAsync(file, callback) {
    fs.readFile(file, 'utf8', callback);
}

async.map(files, readAsync, function(err, results) {
    // results = ['file 1 content', 'file 2 content', ...]
});

Редактировать: Использовать вспомогательную функцию для асинхронного примера.

0 голосов
/ 16 декабря 2014

Существующий ответ не работает для меня.Я нашел пакет NPM, который сделал эту работу: https://www.npmjs.com/package/read-multiple-files. После npm install read-multiple-files в командной строке вот код, который я использовал:

var files = ['1.html', '2.html', '3.html'];

console.log("\n");

readMultipleFiles(files, 'utf8', function(err, inputFiles) {
  if(err) {
    console.log("Read Error: " + err);
  }

  fileOne = inputFiles[0];
  fileTwo = inputFiles[1];
  ...

  console.log(fileOne);
  console.log(fileTwo);

});
...