我正在努力应对Mongoose的承诺,因为我习惯于进行同步编程。
上下文
我有很多类别。每个类别都没有或有一个父类别。 知识与类别相关联。 我想创建一个包含所有类别及其子类别和知识的树。
实际上,它看起来像是具有目录和文件的模型。 预期的输出就像JSON:
[
{"name": "cat0",
"children": [{"name": know0}]
},
{"name": "cat1",
...
]
代码
我使用递归方式。我用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();
} )
});
}
我必须使用此代码返回一个promise,因为在更全局的范围内,它的解析用于返回JSON中的树。
全球范围
findKnowledgeByCategory()
.then((catAndKnow) => res.status(200).json(catAndKnow))
.catch(err => Validation.handleError(res, 500, err));
没有显示错误,但是当我调用该函数时,服务器没有响应。
请注意,它永远不会显示“Débutresolution”... 我正在使用Node 6.11.2所以我不能使用“await”。 任何想法将不胜感激。如果我的问题不相关,我道歉。我想我没有很好地管理我的承诺,但我没有任何线索。
答案 0 :(得分:1)
您不应该使用promise constructor anti-pattern。由于您的方法调用(如find
)已经生成了promise,您应该返回附加到那些的promise链。
其次,保持你的嵌套:由于这个原因发明了承诺,所以不是嵌套then
调用,而是尽快将承诺返回到外链,并链接then
调用那里。
最后,当您在forEach
内创建承诺时,您需要将这些承诺组合成一个承诺。 Promise.all
只是解决这个问题的方法。因此,使用forEach
代替map
,在回调中返回promises,并将结果传递给Promise.all
。
以下是您的代码的外观(未经测试):
static findKnowledgeByCategory(query = null) {
return CategoryModel.find({parent: query}).then((categories) => {
console.log(query + ' : CategoryModel.find success');
return Promise.all(categories.map(cat => {
return KnowledgeModel.find({category: cat._id}).then((knowledges) => {
console.log(query + ' : KnowledgeModel.find success');
cat.knowledges = knowledges;
return Model.findKnowledgeByCategory(cat._id);
}).then((children) => {
cat.children = children;
});
})).then(() => {
console.log(query + ' : Début resolve');
return categories;
})
});
}
答案 1 :(得分:0)
看一下代码的这一部分:
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
,因此永远无法解决。尝试将代码拆分为更小的函数,返回promises,然后将它们排列在一起 - 捕获这样的情况要容易得多。