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"); });
修复说明
- 改用async/await简化异步逻辑:比嵌套Promise更易读,也更容易处理递归的异步等待
- 确保所有异步操作完成后再返回:用
await等待User.find,用Promise.all等待所有子节点的递归Promise完成,保证所有数据加载完毕才返回root - 安全遍历数组:用数组的
map方法遍历response,避免for...in的潜在问题 - 修正条件判断:用
root._id == null同时判断null和undefined,逻辑更准确 - 错误处理优化:把
catch单独提出来,统一处理查询和递归中的错误
内容的提问来源于stack exchange,提问作者Averroes
相关产品推荐
相关产品推荐

