Javascript 获取并解析一个大文件,然后获取下一个文件

Javascript 获取并解析一个大文件,然后获取下一个文件,javascript,garbage-collection,es6-promise,fetch-api,Javascript,Garbage Collection,Es6 Promise,Fetch Api,我必须用ES6获取大约30个文件,每个文件由100MB的文本行组成 我逐行解析文本,计算一些数据点。结果是一个小数组,如 [{"2014":34,"2015":34,"2016":34,"2017":34,"2018":12}] 我在解析文件时遇到内存问题(Chrome会使调试器崩溃),可能是因为我正在使用map解析所有文件: return Promise.all(filenamesArray.

我必须用ES6获取大约30个文件,每个文件由100MB的文本行组成

我逐行解析文本,计算一些数据点。结果是一个小数组,如

[{"2014":34,"2015":34,"2016":34,"2017":34,"2018":12}]
我在解析文件时遇到内存问题(Chrome会使调试器崩溃),可能是因为我正在使用map解析所有文件:

return Promise.all(filenamesArray.map( /*fetch each file in filenamesArray */ )).
then(() => { /*parse them all */ })
我没有发布完整的代码,因为我知道它是错误的。我想做的是

  • 使用fetch加载单个文件
  • 使用如上所述的结果数组解析其文本
  • 返回结果数组并将其存储在某个位置,直到每个文件都被解析
  • 给js引擎/gc足够的时间从内存中清除步骤1中的文本
  • 加载下一个文件(继续执行1,,但仅在完成步骤1-4之后!
  • 但我似乎找不到解决办法。谁能给我举个例子吗? 我不在乎它的承诺、回调函数、异步/等待……只要在启动下一个文件之前对每个文件进行完整的解析

    编辑2020825

    很抱歉我更新得太晚,我现在只是过来解决我的问题。 虽然我很欣赏Josh Linds的回答,但我意识到我仍然有一个关于fetch异步性质的问题,我显然没有很好地描述这个问题: 我该如何处理确保一个文件完成并释放其内存的承诺?我用Promissions.all实现了Joshs解决方案,结果发现这仍然会首先加载所有文件,然后开始处理它们。 幸运的是,我发现了另一个几乎相同的问题:

    所以我学习了异步函数。为了将它们与fetch一起使用,这个问题帮助了我:

    因此,我的最终代码如下所示:

    //returns a promise resolving with an array of all processed files
    loadAndCountFiles(filenamesArray) {
    
            async function readFiles(filenamesArray) {
    
                let resultArray = [];
                for (const filename of filenamesArray) {
                    const response = await fetch(filename);
                    const text = await response.text();
                    //process the text and return a much smaller extract
                    const yearCountObject = processText(text);
                    resultArray.push({
                        filename: filename,
                        yearCountObject: yearCountObject
                    });
                    console.log("processed file " + filename);
                }
                return resultArray;
            }
    
            return new Promise(
                (resolve, reject) => {
                    console.log("starting filecount...");
                    readFiles(filenamesArray)
                        .then(resultArray => {
                            console.log("done: " + resultArray);
                            resolve(resultArray);
                        })
                        .catch((error) => {
                            reject(error);
                        })
                    }
            );
    }
    
    现在,每个文件都会在下一个文件之前被提取和处理。

    全局变量:

    dictionary = {};
    
    大体上:

    fileNamesArray.forEach(fname => readFile(fname));
    
    职能:

    const readFile = (fname) => {
      /* get file */.then(file => {
        /* parse file */
        addToDict(year); // year is a string. Call this when you find a year
      })
    }
    
    const addToDict = (key) => {
      if (dictionary[key]) dictionary[key]++;
      else dictionary[key] = 1;
    }
    

    如果您的代码几乎正确怎么办?你想抛弃所有这些,让志愿者为你做所有的工作,因为这可能是错误的?而且,这一步的每一步都有很多问题;你对这些解决方案有疑问吗?异端猴子,我的代码有大约100行代码,我知道这是错的。它首先加载所有文件内容,然后以一种方式对其进行解析,然后再次加载文件,以另一种方式对其进行解析。几个小时以来,我一直在尝试用步骤1-5重新构造代码,但未能生成任何没有错误的代码。如果你真的想要,我会发布我的代码,但我真的认为阅读它对每个人来说都是浪费时间。我想我只需要一个步骤1,3,5的例子。如果我找到了我的最终解决方案,我很乐意发布。我不需要一个完整的解决方案,我的主要问题是我不知道如何获取和解析,将其标记为gc,然后获取下一个。可以说是同步异步的:)