【问题标题】:NodeJS - Wait Until Streaming Multiple Files Is Complete Before Continuing CodeNodeJS - 等到流式传输多个文件完成后再继续编写代码
【发布时间】:2021-11-27 16:24:59
【问题描述】:

我是 Javascript 和 NodeJS 的新手。我试图在对它们进行一些处理之前读取多个 CSV 文件。我当前的问题是,当我运行代码时,它会在文件读取完成之前尝试执行处理。我想在开始对它们进行任何处理之前加载这两个 CSV。

能否解释一下为什么会发生这种情况以及如何在 Javascript/NodeJS 中解决问题。

function readCSV(path){

    var events = []
    
    fs.createReadStream(path).pipe(csv()).on('data', (row) => {
        events.push(row);
    }).on('end', () => {
        console.log('CSV file successfully processed. Length: ' + events.length);
    }); 

    return events
}

function app(){

    var file_list = listFiles(folder_path);

    for (let i = 0; i < file_list.length; i++) {
        const file = file_list[i];
        var events = readCSV(file)
    }
    
    processCSV(events) // Some processing
}

app();

任何帮助都会很棒,任何关于我如何控制代码执行时间的解释将不胜感激。

【问题讨论】:

    标签: javascript node.js csv asynchronous fs


    【解决方案1】:

    抱歉,您的代码无法编译,所以 a 只能用未经测试的代码回答

    我当前的问题是,当我运行代码时,它会在文件读取完成之前尝试执行处理。

    fs.createReadStream 不读取文件的主要问题 - 它请求文件系统开始读取并在读取某些块时通知您的回调 所以事件'end'稍后会被调用匹配,当readCSV将被完成并返回空结果

    您的代码是按照您期望的同步答案编写的,您可以使用诸如 fs.readFileSync 之类的同步方法使其正常工作

    如何以异步方式修复它?在“on(end)”回调中编写 csv 处理或使用 promises

    Promise 匹配更加简单和线性

    首先让 readCSV 返回 Promise

    function readCSV(path: string){ //return Promise<any[]> 
      return new Promise((resolve) => {
        var events = [];
        fs.createReadStream(path)
          .pipe(csv())
          .on('data', (row) => {
            // this code called in future
            events.push(row);
        }).on('end', () => {
            // this code called in future to, 
            console.log('CSV file successfully processed. Length: ' + events.length);
            resolve(events); //return csv parsed result
        }); 
      })
    }
    

    然后在主应用程序中,使用 Promise.all 等待所有 fileReading 承诺

    function app(){
      // i don't know what is listFiles,
      // i hope it returns sync result
      var file_list = fs.listFiles(folder_path);
    
      const dataPromises: Promise[] = []
      for (let i = 0; i < file_list.length; i++) {
          const file = file_list[i];
          //launch reading
          dataPromises.push(readCSV(file))
      }
      Promise.all(dataPromises).then(result => {
        //this code will be called in future after all readCSV Promises call resolve(..)
        for(const events of result){
          processCSV(events);    
        }
      })
    }
    

    【讨论】:

    • 谢谢,看起来它与 Promises 一起工作
    猜你喜欢
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多