Как и все мы, вы являетесь еще одной жертвой асинхронного ввода-вывода.При асинхронных вызовах, если вы зациклились на большом количестве файлов, Node.js начнет открывать файловый дескриптор для каждого файла для чтения, а затем будет ждать действия, пока вы его не закроете.
Дескриптор файла остается открытым доресурс доступен на вашем сервере, чтобы прочитать его.Даже если ваши файлы небольшие, а чтение или обновление выполняется быстро, это займет некоторое время, но в то же время ваш цикл не останавливается, чтобы открыть дескриптор новых файлов.Так что, если у вас слишком много файлов, предел скоро будет достигнут, и вы получите прекрасный EMFILE .
. Существует одно решение - создать очередь, чтобы избежать этого эффекта.
Спасибо людям, которые написали Async , для этого есть очень полезная функция.Существует метод с именем Async.queue , вы создаете новую очередь с ограничением, а затем добавляете имена файлов в очередь.
Примечание. Если вам нужно открыть много файлов, это будетХорошая идея хранить файлы, которые открыты в данный момент, и не открывать их бесконечно.
const fs = require('fs')
const async = require("async")
var q = async.queue(function(task, callback) {
console.log(task.filename);
fs.readFile(task.filename,"utf-8",function (err, data_read) {
callback(err,task.filename,data_read);
}
);
}, 4);
var files = [1,2,3,4,5,6,7,8,9,10]
for (var file in files) {
q.push({filename:file+".txt"}, function (err,filename,res) {
console.log(filename + " read");
});
}
Вы можете видеть, что каждый файл добавляется в очередь (имя файла console.log), но только когда текущийочередь под пределом, который вы установили ранее.
async.queue получает информацию о доступности очереди посредством обратного вызова, этот обратный вызов вызывается только тогда, когда файл данных читается и любое действие, которое вам нужно сделать, выполнено.(см. метод fileRead)
Таким образом, вы не можете быть перегружены дескриптором файлов.
> node ./queue.js
0.txt
1.txt
2.txt
0.txt read
3.txt
3.txt read
4.txt
2.txt read
5.txt
4.txt read
6.txt
5.txt read
7.txt
1.txt read (biggest file than other)
8.txt
6.txt read
9.txt
7.txt read
8.txt read
9.txt read