我有一个包含大约 500,000 个 JSON 文件路径的数组。文件的平均大小为 20-100 KB。每个 JSON 文件都包含一个需要读取的数值并将其添加到累计总数中。
如果我在迭代中同步读取文件,处理速度很快就会变慢。如果我在迭代中异步读取文件,我会收到“打开的文件太多”错误。
我的问题是,什么方法、迭代和文件处理方法适合执行此任务?我对 Node.js 比较陌生,并且正在努力解决上述问题。
function readFiles(filePaths) {
filePaths.forEach(filePath => {
fs.readFile(filePath, 'utf8', (err, data) => {
// do somthing
});
});
}
readFiles(filePaths); // it's an array of strings
当您使用
filePaths.forEach
时,它会快速遍历大数组,每次它都会启动一个异步 fs.readFile
调用,该调用快速返回一个承诺,然后执行打开文件并在后台处理它的工作。这意味着您很快就会同时打开大量文件,并且遇到您所看到的问题。
要限制一次打开的文件数量,您需要确保不会同时创建太多异步调用。一种方法是使用 PromisePool(请参阅 https://www.npmjs.com/package/@supercharge/promise-pool)。这允许您将同时 Promise 的数量设置为 50 或任何适合您情况的值,并且它将在之前的文件完成时启动新文件读取。
使用
PromisePool
您的代码可能如下所示:
import { PromisePool } from '@supercharge/promise-pool'
function readFiles(filePaths) {
return PromisePool
.withConcurrency(50)
.for(filePaths)
.process(async (filePath) => {
return fs.readFile(filePath, 'utf8', (err, data) => {
// do something
}
});
}
readFiles(filePaths); // it's an array of strings
本质上与您所拥有的流程相同,但通过使用
PromisePool.for().process()
,它将确保在任何时候只有特定数量处于活动状态。这应该可以防止您因一次打开太多文件而导致资源超载。