我的图书馆:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('graceful-fs'));
const path = require('path');
const xml2js = Promise.promisifyAll(require('xml2js'));
我有大量的 XML 文件要解析。我可以使用此函数创建所有文件的路径数组:
function getFileNames(rootPath) {
// Read content of path
return fs.readdirAsync(rootPath)
// Return all directories
.then(function(content) {
return content.filter(function(file) {
return fs.statSync(path.join(rootPath, file)).isDirectory();
});
})
// For every directory
.map(function(directory) {
// Save current path
let currentPath = path.join(rootPath, directory);
// Read files in the directory
return fs.readdirAsync(currentPath)
// Filter out the XMLs
.filter(function(file) {
return path.extname(file) === '.XML';
})
// Return path to file
.map(function(file) {
return path.join(rootPath, directory, file);
});
})
// Flatten array of results
.reduce(function(a, b) {
return a.concat(b);
});
}
现在我想遍历每个文件并解析它。
我有 2 个函数可以这样做:
function openFile(filePath) {
return fs.readFileAsync('./' + filePath)
.then(function(fileData) {
return fileData;
});
}
function parseFile(data) {
return xml2js.parseStringAsync(data)
.then(function(xmlObject) {
return xmlObject;
});
}
现在当我用 .map 调用它时(GetFileNames
函数输出一个包含超过 20k 字符串和文件路径的数组)函数:
getFileNames('./XML')
.map(function(file) {
openFile(file)
.then(function(data) {
parseFile(data)
.then(function(object) {
console.log(object);
});
});
});
我收到 javascript 堆内存不足错误:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
但是当我通过传入实际文件的路径来运行函数一次时:
openFile('./XML/2016-10-1/EUROTIPOLD2016-10-1T00-00-22.5756240530.XML')
.then(function(data) {
parseFile(data)
.then(function(object) {
console.log(object);
});
});
我得到了想要的输出。
我做错了什么?
最佳答案
迭代 nK
文件是异步发生的。
1) 你正在获取文件列表
2) 通过执行 .map
您正在调用 openFile
、parseFile
,它们是异步函数,读取和解析需要时间。
因此,由于异步性,它会继续处理下一个文件,而无需等待完成前一个文件来调用垃圾收集器来清扫内存,这就是内存不足的问题。
考虑一次读取 20K 个不同大小的文件。
所以这是解决方案:
使用async
来同步(eachSeries
)或控制(eachLimit
)迭代。
const async = require('async'); // install: npm i --save async
let files = getFileNames('./XML');
// eachLimit(files, 3,
async.eachSeries(files,
(file, next) => {
openFile(file)
.then(
parseFile,
(err) => {
console.error('Cannot open file:', file, err);
next();
})
.then(
object => { // successfully parsed file, so log it out and proceed to next file
console.log(object);
next();
},
(err) => {
console.error('Cannot parse data from file:', file, err);
next();
});
});
附注请随时在我的回答中发表评论并修复代码问题。
关于Javascript - .map 内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40721024/