JavaScript 使用 csvtojson 读取目录多CSV文件返回客户端的异步问题
核心问题定位
当前代码存在异步执行时序错位:
Array.prototype.forEach不具备异步等待能力,即便回调函数用async修饰,forEach本身也不会阻塞等待所有回调内部的Promise执行完成- 调用
fetchData()时,代码仅会把所有CSV转JSON的异步任务排入事件队列,不会等待任务执行结束,就直接运行到res.send(jsonData)逻辑;此时jsonData数组还未填充任何转换结果,因此返回给客户端的是空数据。
修正实现方案
具体调整逻辑如下:
- 将原有
forEach遍历替换为map遍历,把每个文件的CSV转换操作封装为独立的Promise对象 - 使用
Promise.all并行等待所有文件的处理任务完成,拿到全量数据后再执行响应返回 - 把路由接口的回调函数改造为async函数,支持await阻塞后续同步逻辑
- 补充try/catch异常捕获,避免异步流程中的错误导致接口无响应或进程崩溃
修正后的完整代码如下:
router.get("/covidData/", async (req, res) => { try { const jsonData = []; // 保留原有目录读取逻辑 const files = fs.readdirSync(__dirname.replace("routes", "public/covidData")); // 为每个文件生成独立的异步处理Promise const fileProcessTasks = files.map(async (file) => { const currentFilePath = __dirname.replace("routes", "public/covidData/" + file); return await csvtojson({ includeColumns: /Date Announced|Detected State|Current Status/, }).fromFile(currentFilePath); }); // 等待所有文件的转换任务全部完成 const processResults = await Promise.all(fileProcessTasks); // 合并所有文件返回的JSON数组 jsonData.push(...processResults.flat()); // 全量数据加载完成后再返回响应 res.send(jsonData); } catch (error) { res.status(500).send({ message: "CSV数据读取失败", errorDetail: error.message }); } });
补充注意事项
- 不要在无等待能力的循环中嵌套async操作:
forEach、普通同步for循环如果内部嵌套await逻辑,都会出现本次遇到的时序错位问题 - 如果需要提升单文件处理的错误容忍度(即某个文件读取失败不影响其他文件的数据返回),可以将
Promise.all替换为Promise.allSettled,遍历返回结果时筛选出状态为fulfilled的成员做数据合并 - 相比串行逐文件读取的模式,
Promise.all的并行处理逻辑可以大幅降低多文件读取的总耗时
内容的提问来源于stack exchange,提问作者atulsmania
相关产品推荐
相关产品推荐

