Javascript - .map 内存不足

标签 javascript node.js

我的图书馆:

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 您正在调用 openFileparseFile,它们是异步函数,读取和解析需要时间。


因此,由于异步性,它会继续处理下一个文件,而无需等待完成前一个文件来调用垃圾收集器来清扫内存,这就是内存不足的问题。

考虑一次读取 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/

相关文章:

javascript - React-Redux 将 google Places api 变成了 promise

javascript - Angular 2 App Testing,如何访问和操作html元素?

node.js - 通过 nextPageToken 在 Google Drive API 中检索下一页的正确语法是什么

javascript - NodeJS ZIP 文件下载损坏

javascript - 如果在 EnsureIndex MongoDB Node 中发现重复则显示错误

c# - Modal PopUp Extender 中的 GridView ?

javascript - 由于范围问题,ng-click 不会在 ng-repeat 内触发

javascript - 直接为对象标签提供数据

node.js - 电子邮件未通过 1and1 smtp 主机 nodemailer caddy 发送

node.js - 错误: input is self closing and should not have content