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

Express路由结合递归Promise获取MongoDB数据返回问题求助

问题分析与修复方案

核心问题

你的代码存在4个关键问题,导致数据还没加载完成就返回了空对象:

  • 异步时机错误:Promise.resolve在User.find异步查询完成前就执行了,直接返回初始的空root
  • 递归异步未处理:递归调用fetchTrees返回的是Promise,但你直接把Promise赋值给了descendants,没有等待它完成并填充实际数据
  • 数组遍历不安全:用for...in遍历MongoDB返回的数组,可能会遍历到数组原型链上的额外属性
  • 条件判断逻辑错误:root._id !== null || root._id !== undefined永远为真,无法正确触发reject

修复后的完整代码

const fetchTrees = async (source, root) => {
    // 先判断root是否有效,无效直接抛出错误
    if (root._id == null) {
        throw new Error("No tree data");
    }

    // 等待MongoDB查询完成
    const response = await User.find({ referrer: source });
    
    // 遍历所有子节点,用Promise.all等待所有递归完成
    await Promise.all(response.map(async (person) => {
        const document = person._id;
        root[document] = {
            name: `${person.first_name} ${person.last_name}`,
            uppLine: person.uppLine,
            _id: document
        };
        // 等待递归完成,把结果赋值给descendants
        root[document].descendants = await fetchTrees(document, root[document]);
    }));

    console.log("Hey", root);
    return root;
};

// Express路由里的调用
fetchTrees(source, root)
    .then((result) => {
        console.log("Returnnn", result);
        res.status(200).send(result);
    })
    .catch((err) => {
        console.error(err);
        res.status(404).send("No tree found");
    });

修复说明

  1. 改用async/await简化异步逻辑:比嵌套Promise更易读,也更容易处理递归的异步等待
  2. 确保所有异步操作完成后再返回:用await等待User.find,用Promise.all等待所有子节点的递归Promise完成,保证所有数据加载完毕才返回root
  3. 安全遍历数组:用数组的map方法遍历response,避免for...in的潜在问题
  4. 修正条件判断:用root._id == null同时判断null和undefined,逻辑更准确
  5. 错误处理优化:把catch单独提出来,统一处理查询和递归中的错误

内容的提问来源于stack exchange,提问作者Averroes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:21:06