You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:39:51