fs.readFile修改全局数组作用域后外部无法访问的问题求解
解决方案
核心问题梳理
- 你给
async函数里的回调版fs.readFile加await是无效的,回调版API不返回Promise,await不会等待读取完成就会执行后续代码,所以才需要用setTimeout强行延时,逻辑非常不稳定 - 全局
data变量和异步执行顺序混乱,路由中两个fs.readFile是并行执行的,会在timeSeries逻辑没跑完就去读还没更新的timeseries.json - 没必要写中间文件,异步逻辑理顺后可以直接返回处理好的数据
修改后的代码
第一步:重写timeSeries函数
// 引入fs的promise版本,配合async/await使用 const fs = require('fs').promises; async function timeSeries(obj) { // 函数内部声明变量,不要用全局变量避免作用域污染 const data = [ { original_value: [] } ]; // await等待文件读取完成,不需要嵌套回调 const datas = await fs.readFile(`./api/assignment_data/${obj._id}.json`, "utf-8"); const filedata = JSON.parse(datas); filedata.forEach(line => data[0].original_value.push(line.original_value)); // 直接返回处理好的数组,不需要写入中间文件也不需要加延时 return data; }
第二步:重写路由逻辑
router.route("/api/debug/:num").get(async (req, res) => { try { // 按顺序执行异步操作,先读取metrics.json const metricsData = await fs.readFile("./api/assignment_data/metrics.json", "utf8"); const objdata = JSON.parse(metricsData); // 等待timeSeries处理完成,直接拿到返回的数组 const timeSeriesResult = await timeSeries(objdata[req.params.num]); // 直接返回结果,不需要读取中间文件 res.json(timeSeriesResult); } catch (error) { // 统一捕获所有异步错误 console.log(error); res.status(500).json({ error: "数据处理失败" }); } })
改动说明
- 全部替换为Promise版
fsAPI,配合async/await彻底解决回调地狱问题,不需要再用setTimeout赌执行时间 - 砍掉中间文件写入/读取的冗余逻辑,直接返回处理好的数据,性能更高逻辑更清晰
- 统一用
try/catch捕获所有异步操作的错误,避免未处理异常导致服务崩溃
内容的提问来源于stack exchange,提问作者yatrik
相关产品推荐
相关产品推荐

