2016-11-21 50 views
2

我的图书馆:使用Javascript - .MAP运行内存

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

我得到所需的输出。

我在做什么错?

+0

所以你说,当你以某种方式使用varaible,而不是它的工作原理硬编码字符串的??? – epascarello

+0

对不起,编辑了这个问题。我说当我运行函数一次没有.map函数时它的工作原理(通过传递一个字符串与文件的路径)。当我在.map函数中运行它时,内存不足。 –

+1

您尝试打开多少个文件?不要忘记异步函数,Node.js尝试同时打开所有文件,而不是一个接一个地打开。 – Fefux

回答

1

迭代nK文件发生异步的。

1)你得到这样做的文件

2)名单.map你打电话openFileparseFile是异步函数,它需要时间来阅读和分析。


是因为asynchronousity的前进到下一个文件,而无需等待完成前一个调用垃圾回收器来扫描存储器,这里是内存不足的问题。

想想一次读取不同大小的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(); 
     }); 
}); 

p.s.随时在我的答案中发表评论并解决代码问题。

+1

未使用你的代码直接,但开始使用async.eachSeries,它解决了我的问题。谢谢 –

+0

@MihaŠušteršič实际上这是一个例子(:你可以自由定义你的代码,因为你愿意 – num8er

0

这是为您的工作负载的更多资源需求的简单情况。我会考虑增加堆大小以满足您的需求,而不是更改源代码。

我建议--max_old_space_size要建立相应的满足需求 - 这可能是一个反复的过程,但。

希望这会有所帮助。

+0

我认为只有在没有其他问题或情况下才可以解决此问题最好先调试问题,并尽可能修复或优化,只有在严格需要的情况下,才能继续根据服务器的负载级别为节点进程提供更多资源。 –