Node.js异步函数异常:REST API提前响应返回空数组
问题分析
你的代码核心问题是**forEach不支持异步等待**:当你在forEach中使用async函数时,它会直接遍历所有元素并启动异步任务,但不会等待这些任务全部完成。外层的await fs.readdir(...)仅会等待目录读取完成,不会等待后续的文件读取操作,因此代码会提前执行res.send(contacts),此时contacts数组还未被填充。
解决方案
有两种可靠的修复方式:
方法1:使用for...of循环(顺序读取文件)
for...of原生支持异步等待,能确保每个文件读取完成后再处理下一个:
const fs = require("fs/promises"); app.get("/contacts", async (req, res) => { const dir_name = "./contacts"; const contacts = []; // 用await替代then,避免混合写法 const filenames = await fs.readdir(dir_name); // 使用for...of遍历,等待每个异步操作完成 for (const filename of filenames) { const jsonString = await fs.readFile(`${dir_name}/${filename}`, "utf-8"); contacts.push(JSON.parse(jsonString)); } console.log(contacts); res.send(contacts); });
方法2:使用Promise.all(并行读取文件,效率更高)
如果不需要按顺序读取文件,Promise.all可以并行处理所有文件读取操作,性能更优:
const fs = require("fs/promises"); app.get("/contacts", async (req, res) => { const dir_name = "./contacts"; const filenames = await fs.readdir(dir_name); // 将每个文件读取任务转为Promise,等待全部完成后直接得到结果数组 const contacts = await Promise.all( filenames.map(async (filename) => { const jsonString = await fs.readFile(`${dir_name}/${filename}`, "utf-8"); return JSON.parse(jsonString); }) ); console.log(contacts); res.send(contacts); });
额外建议
- 避免混合使用
await和.then(),代码会更易读且不易出错; - 建议添加
try/catch块处理文件读取或JSON解析失败的情况,防止接口崩溃。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

