Mongoose递归Promise未Resolve导致服务器无响应问题求助
我帮你分析下问题根源,然后给出适配Node.js 6的解决方案:
问题核心原因
你的代码之所以卡住、永远不打印“Début resolve”,是因为内部的Promise没有被正确resolve,导致整个Promise链一直处于pending状态:
- 你用
categories.forEach遍历分类时,发起了KnowledgeModel.find和递归调用findKnowledgeByCategory这些异步操作,但forEach不会等待这些Promise完成,会直接往下走 - 你创建的那个内部
new Promise,从头到尾都没有调用resolve(),它永远不会完成,所以外层的.then(() => { console.log(query + ' : Début resolve'); ... })永远不会触发
修正后的代码(适配Node.js 6)
static findKnowledgeByCategory(query = null) { return new Promise((resolve, reject) => { CategoryModel.find({ parent: query }) .then((categories) => { console.log(query + ' : CategoryModel.find success'); // 把每个分类的异步处理逻辑转换成Promise数组 const categoryTasks = categories.map(cat => { // 先获取当前分类下的知识,再递归获取子分类 return KnowledgeModel.find({ category: cat._id }) .then((knowledges) => { console.log(query + ' : KnowledgeModel.find success'); cat.knowledges = knowledges; // 等待递归获取子分类的Promise完成 return Model.findKnowledgeByCategory(cat._id); }) .then((childrenCategories) => { cat.children = childrenCategories; return cat; // 返回处理好的分类对象 }); }); // 等待所有分类的异步任务都完成后,再resolve外层Promise Promise.all(categoryTasks) .then(() => { console.log(query + ' : Début resolve'); resolve(categories); }) .catch(reject); // 把内部错误传递给外层reject }) .catch((err) => { console.error(err); reject(err); }); }); }
关键改动说明
- 用
map替代forEach:forEach不会处理异步返回值,而map可以把每个分类的异步逻辑转换成Promise,收集成数组后用Promise.all等待全部完成 - 串联异步操作:每个分类的“获取知识→递归子分类”被整合成一条Promise链,确保前一步完成后再执行下一步
- 正确触发resolve:只有当所有分类的异步任务都完成后,才调用
resolve(categories),让外层Promise正常完成 - 统一错误处理:把内部异步操作的错误传递给外层
reject,避免错误被静默吞掉,方便排查问题
Node.js 6虽然不支持async/await,但Promise.all和链式Promise是完全支持的,这个方案可以完美解决你的问题。
内容的提问来源于stack exchange,提问作者Yukeer
相关产品推荐
相关产品推荐

