NodeJS如何等待多个CSV文件流读取完成后再执行后续处理代码
问题出现原因
该问题核心是Node.js的异步非阻塞执行机制导致的:
fs.createReadStream以及配套的流事件监听(data、end事件)都是异步操作,代码不会等待事件触发完成就会继续往下执行,所以你的readCSV函数会在流还没读完的时候就直接返回空的events数组。- 循环调用
readCSV时所有读取任务都是并行触发的,没有等待所有文件读取完成的逻辑,会直接执行后续的processCSV,此时拿到的events要么是空数组,要么是还没填充完成的不完整数据。 - 原有代码中循环内部每次用
var events覆盖变量,最后调用processCSV时只能拿到最后一次调用readCSV的返回值,无法收集所有文件的数据。
解决方案
核心思路是把readCSV封装为返回Promise的异步函数,再通过async/await + Promise.all等待所有文件读取完成后再执行处理逻辑,改造后的代码如下:
const fs = require('fs'); const csv = require('csv-parser'); // 改造readCSV为返回Promise的异步函数 function readCSV(path) { return new Promise((resolve, reject) => { const events = []; fs.createReadStream(path) .pipe(csv()) .on('data', (row) => events.push(row)) .on('end', () => { console.log('CSV file successfully processed. Length: ' + events.length); resolve(events); // 读取完成后返回当前文件的所有数据 }) .on('error', (err) => reject(err)); // 捕获读取过程中的错误 }); } // 改造app为async异步函数 async function app() { try { const file_list = listFiles(folder_path); // 同时发起所有文件的读取任务,等待全部读取完成 const allFileData = await Promise.all(file_list.map(file => readCSV(file))); // 把所有文件的数组合并为一个数组 const allEvents = allFileData.flat(); // 此时所有数据已加载完成,再执行处理逻辑 processCSV(allEvents); } catch (err) { console.error('执行出错:', err); } } app();
Node.js 异步执行时机控制常用方法
- 回调函数:异步操作完成后调用预先传入的回调函数执行后续逻辑,是最基础的异步控制方式,多层嵌套容易产生回调地狱问题,不推荐复杂场景使用。
- Promise:ES6 标准提供的异步容器,用来表示异步操作的最终状态和结果,支持链式调用,可解决回调嵌套问题。
- async/await:基于 Promise 实现的语法糖,可以用类似同步代码的写法编写异步逻辑,可读性极高,
await会暂停当前async函数的执行,等待目标 Promise 状态变更后再继续往下执行。 - 批量异步控制:
- 等待所有并行异步任务全部完成,使用
Promise.all() - 只需等待第一个完成的异步任务,使用
Promise.race() - 需要按顺序逐个执行异步任务,可通过
for...of循环配合await逐一执行
- 等待所有并行异步任务全部完成,使用
内容的提问来源于stack exchange,提问作者Jordfoz16
相关产品推荐
相关产品推荐

