我正在运行此续集查询,该查询返回一些论坛帖子。对于每个结果,我运行第二个查询,该查询为我提供了每个论坛帖子的类别/标签。现在,forEach循环在所有查询运行之前结束,因为它是异步的,我知道那部分。如何正确处理此问题并执行我想做的事情?我想将标签/类别数组附加到每个帖子,并将帖子数组发送到ejs视图并调用next();。
我尝试了promise.all()和async-await,我确实以这种方式分别获得了类别。但我希望将类别附加到每个发布对象。
Forum.findAll({
attributes: ["f_post_id", "f_post_title", "like_count", "createdAt"],
limit: limitPost.FORUM,
subQuery: false,
raw: true,
group: ['forum.f_post_title'],
include: [{
attributes: ["user_name"],
model: User,
required: true, // returns everything in a clean single object format
// setting it to false, results in nested arrays
}, {
attributes: [[Sequelize.fn("COUNT", Sequelize.col("forum_answers.answer_id")), "ansCount"]],
model: ForumAnswer,
required: true,
}]
})
.then(fetchedPost => {
fetchedPost.forEach(post => {
ForumTag.findAll({
attributes: [],
raw: true,
where: {
f_post_id: post.f_post_id,
},
include: [{
attributes: ["tag_name"],
model: Tag,
required: true,
}]
})
.then(postTags => {
post.tags = postTags.map(postTag => postTag["tag.tag_name"]);
})
.catch(err => console.log(err));
});
res.locals.fetchedPost = fetchedPost;
next();
})
.catch(err => console.log(err));
这是下面的预期结果:
{
f_post_id: 1,
f_post_title: 'learn js',
like_count: 12,
createdAt: 2019-05-19T00:00:00.000Z,
'user.user_name': 'mrscx',
'forum_answers.ansCount': 3,
tags: [ 'JavaScript', 'Database' ]
}
但是因为forEach循环结束,所以未附加标签。
我该如何解决?
答案 0 :(得分:0)
findAll()
调用是异步的,因此forEach
为每个帖子调用ForumTag.findAll()
,但是在修改生效之前立即返回。另外,您需要在修改后在模型上调用save()
方法以使其永久(例如post.save()
之后的post.tags = ...
)
您可以尝试这样的事情:
let promises = [];
fetchedPost.forEach(post => {
ForumTag.findAll({
attributes: [],
raw: true,
where: {
f_post_id: post.f_post_id,
},
include: [{
attributes: ["tag_name"],
model: Tag,
required: true,
}]
})
.then(postTags => {
post.tags = postTags.map(postTag => postTag["tag.tag_name"]);
promises.push(post.save());
})
.catch(err => console.log(err));
});
Promise.all(promises).then(() => {
res.locals.fetchedPost = fetchedPost;
next();
}).catch(err => {
throw err;
});
答案 1 :(得分:0)
从外观上看,问题可能出在您处理承诺的方式上。您实际上并不是在等待forEach
循环中的promise,而是在此之前返回结果。解决该问题的一种方法是:
Forum.findAll({
attributes: ["f_post_id", "f_post_title", "like_count", "createdAt"],
limit: limitPost.FORUM,
subQuery: false,
raw: true,
group: ['forum.f_post_title'],
include: [{
attributes: ["user_name"],
model: User,
required: true, // returns everything in a clean single object format
// setting it to false, results in nested arrays
}, {
attributes: [[Sequelize.fn("COUNT", Sequelize.col("forum_answers.answer_id")), "ansCount"]],
model: ForumAnswer,
required: true,
}]
})
.then(fetchedPost => {
return Promise.all(fetchedPost.map(post =>
ForumTag.findAll({
attributes: [],
raw: true,
where: {
f_post_id: post.f_post_id,
},
include: [{
attributes: ["tag_name"],
model: Tag,
required: true,
}]
})
.then(postTags => {
post.tags = postTags.map(postTag => postTag["tag.tag_name"]);
return post.save();
})
.catch(err => console.log(err));
}).then(() => {
res.locals.fetchedPost = fetchedPost;
next();
});
})
我敢肯定,还有更优雅的方法可以做这种事情。但这是对原始代码的最少修改。