NodeJS - 等到流式传输多个文件完成后再继续编写代码

Posted

技术标签:

【中文标题】NodeJS - 等到流式传输多个文件完成后再继续编写代码【英文标题】:NodeJS - Wait Until Streaming Multiple Files Is Complete Before Continuing Code 【发布时间】: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();

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

【问题讨论】:

【参考方案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 一起工作

以上是关于NodeJS - 等到流式传输多个文件完成后再继续编写代码的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 等到 Firestore getDocuments() 完成后再继续

Mp3 播放类播放列表中的歌曲,但要等到一首完成后再继续

nodejs 等到循环中的所有 MongoDB 调用完成

gRPC 服务器端流式传输:如何无限期地继续流式传输?

流媒体整理

如何等到文件完成写入后再使用它?