链式Promise使用await时未完全解析,CSV批量处理异常
问题分析与修复方案
问题根源
你的代码里,创建的Promise在第一个CSV文件解析完成时就调用了resolve——Promise的状态一旦变为已完成就无法再更改,导致后续文件的解析逻辑还没执行完,外层的await就拿到了不完整的结果。虽然全局变量ofsActivities会继续收集后续文件的数据,但外层已经提前获取了早期的结果,自然看不到最终完整的长度。
修复方案
核心思路
- 将单个CSV文件的解析逻辑封装成独立Promise,通过
Promise.all等待所有文件解析完成后再统一返回结果 - 替换手动封装的
readdir为Node.js内置的fs.promises.readdir,简化异步逻辑 - 用更可靠的方式判断CSV文件,避免字符串分割的潜在问题
- 移除全局变量,改用局部变量管理数据,避免全局状态污染
修改后的完整代码
const fs = require(`fs`).promises; const path = require(`path`); const csv = require(`fast-csv`); const currDir = path.join(__dirname, `../Downloads/`); // 严谨判断CSV文件(支持大写.CSV后缀) const isCsvFile = (filename) => { return path.extname(filename).toLowerCase() === `.csv`; }; // 解析单个CSV文件,返回Promise const parseSingleCsv = async (filePath) => { return new Promise((resolve, reject) => { const fileData = []; csv .parseFile(filePath) .on(`data`, (data) => { // 这里处理单行数据,示例:直接存入数组 fileData.push(data); }) .on(`error`, (error) => reject(error)) .on(`end`, () => resolve(fileData)); }); }; const ofsDataObjectArray = async () => { // 读取目录并过滤出CSV文件 const allFilenames = await fs.readdir(currDir); const csvFilenames = allFilenames.filter(isCsvFile); // 并行解析所有CSV文件,等待全部完成 const allFileResults = await Promise.all( csvFilenames.map(async (filename) => { const fullPath = path.join(currDir, filename); console.log(`Reading File: ${filename}`); return parseSingleCsv(fullPath); }) ); // 将多个文件的数组合并为一个扁平数组(按需调整) return allFileResults.flat(); }; (async () => { try { const fullList = await ofsDataObjectArray(); console.log(fullList.length); // 现在会输出所有CSV文件的总数据长度 } catch (err) { console.error(`处理出错:`, err); } })();
关键修改点说明
- 用
fs.promises.readdir替代手动封装的异步读取逻辑,代码更简洁且符合Node.js现代异步规范 isCsvFile函数通过path.extname获取文件后缀,避免了文件名无后缀、多后缀或大小写差异的问题- 每个CSV文件的解析都封装为独立Promise,通过
Promise.all确保所有文件处理完成后才返回结果 - 移除全局变量
ofsActivities,改用局部变量管理单文件数据,最后合并所有结果,避免全局状态混乱 - 添加
try/catch捕获异步过程中的错误,增强代码健壮性
内容的提问来源于stack exchange,提问作者Maven
相关产品推荐
相关产品推荐

