Javascript Mongoose中的承诺递归返回问题
我正在与Mongoose的承诺作斗争,因为我习惯于同步编程 上下文 我有很多类别。每个类别没有父类别或只有一个父类别。 知识与类别相关联。 我想创建一个包含所有类别及其子类别和知识的树 实际上,它看起来像一个带有目录和文件的模型。 预期的输出类似于JSON:Javascript Mongoose中的承诺递归返回问题,javascript,json,node.js,mongoose,promise,Javascript,Json,Node.js,Mongoose,Promise,我正在与Mongoose的承诺作斗争,因为我习惯于同步编程 上下文 我有很多类别。每个类别没有父类别或只有一个父类别。 知识与类别相关联。 我想创建一个包含所有类别及其子类别和知识的树 实际上,它看起来像一个带有目录和文件的模型。 预期的输出类似于JSON: [ {"name": "cat0", "children": [{"name": know0}] }, {"name": "cat1", ... ] 代码 findKnowledgeByCate
[
{"name": "cat0",
"children": [{"name": know0}]
},
{"name": "cat1",
...
]
代码
findKnowledgeByCategory()
.then((catAndKnow) => res.status(200).json(catAndKnow))
.catch(err => Validation.handleError(res, 500, err));
我使用递归的方法。我使用null调用函数(它获取所有根类别),然后递归调用将应用于子类别
static findKnowledgeByCategory(query = null){
return new Promise((resolve, reject) => {
CategoryModel.find({parent: query})
.then((categories) => {
console.log(query + ' : CategoryModel.find success');
return new Promise((resolve, reject) => {
console.log(query + ' : new Promise');
categories.forEach(cat => { // cat == { _id: ..., parent: ..., name: 'smthng' }
KnowledgeModel.find({category: cat._id})
.then((knowledges) => {
console.log(query + ' : KnowledgeModel.find success');
cat.knowledges = knowledges;
Model.findKnowledgeByCategory(cat._id)
.then((categories) =>{
cat.children = categories;
});
})
})
}).then(() => {
console.log(query + ' : Début resolve');
return resolve(categories);
})
})
.catch((err) =>{
console.log(err);
return reject();
} )
});
}
我必须用这段代码返回一个承诺,因为在更全局的范围内,它的解析用于返回JSON中的树
全球范围
findKnowledgeByCategory()
.then((catAndKnow) => res.status(200).json(catAndKnow))
.catch(err => Validation.handleError(res, 500, err));
没有显示错误,但是当我调用函数时,服务器没有响应
请注意,它永远不会显示“Début resolve”。。。
我正在使用节点6.11.2,所以不能使用“等待”。
任何想法都将不胜感激。如果我的问题与此无关,我深表歉意。我想我没有很好地履行我的承诺,但我没有任何线索。看看这部分代码:
return new Promise((resolve, reject) => {
console.log(query + ' : new Promise');
categories.forEach(cat => {
KnowledgeModel.find({category: cat._id})
.then((knowledges) => {
console.log(query + ' : KnowledgeModel.find success');
cat.knowledges = knowledges;
Model.findKnowledgeByCategory(cat._id)
.then((categories) =>{
cat.children = categories;
});
})
})
})
您从未在此承诺内调用resolve
或reject
,因此它从未被解决。尝试将代码拆分为较小的函数,然后将它们排列在一起—这样更容易捕捉到这种情况。您不应该使用。由于您的方法调用(如find
)已经产生承诺,您应该返回附加到这些承诺的承诺链
其次,保持你的嵌套水平:承诺就是因为这个原因而产生的,所以不要嵌套然后
调用,而是尽快将承诺返回到外链,然后在那里链接一个然后
调用
最后,当您在forEach
中创建承诺时,您需要以某种方式将这些承诺组合成一个承诺<代码>承诺。所有的都只是补救措施。因此,不要使用forEach
,而是在回调中使用map
返回承诺,并将结果传递给Promise.all
以下是代码的外观(未经测试):
这是第六级回叫地狱。您确实需要将此代码分解为更小的片段、函数或异步/等待块。或者使用模块。因为现在的调试就是它被称为地狱的原因。谢谢你的回复。为了解释这一点,我尝试在forEach()阵营之后放置一个resolve(),但这不是我想要的。因为它将实现承诺,尽管循环尚未完成。如何处理(换句话说,承诺中的同步过程)?我也尝试了没有“返回”,但没有更好的结果。通过使用
category.forEach
,您正在迭代每个类别,并对每个类别执行一些查询。这意味着您应该等待所有查询结束。看看这个方法。但首先,请尝试将这个大函数重新组织为较小的函数,并将它们组合在一起-这将使代码更具可读性。谢谢您的帮助。看起来它没有进入then(children)中,但我想我自己可以找到。如果执行没有到达然后回调,请检查知识模型。find({category:cat.\u id})
承诺可能会拒绝而不是履行。你可以在之后链接一个。catch
,然后((儿童)
来检查。事实上,我刚才注意到了。谢谢。谢谢你的反馈。