我知道可能已经有人问过这个问题。但是我不明白事情是如何工作的,这就是为什么我要创建新线程。
con.query(sql,[req.params.quizId],(err,rows,fields)=>{
//rows contains questions
if(err) throw err;
else{
let object={};
rows.forEach((item,index)=>{
object=item;
//here iam passing question id to get choices a async function
getChoices(item.id)
.then(data=>{
object.choices=data;
//save the question array
response.push(object);
//res.send(response);
});
})
res.send(response) //return empty array
}
});
function getChoices(questionId) {
let sql='SELECT id,text FROM `question_choices` where question_id=?';
return new Promise((resolve, reject) => {
con.query(sql,[questionId],(err,rows,fields)=>{
if(err) throw err;
else {
resolve(rows);
}
})
})
}
我尝试了几件事,但没有任何效果。我认为for循环没有等待诺言完成,而是直接发送响应。那里发生了一些异步问题。
我可以从数据库中获取所有问题,对于每个问题,我需要获得所需的相应选择。
类似的东西
[{id:'xx', text:'yy',choices:[{id:'c',text:'kk']},etc]
答案 0 :(得分:2)
forEach
同步运行 。您正在寻找Promise.all
,它接受Promises
的数组,并在所有Promises解析后解析为解析值的数组。要将rows
数组转换为Promises
数组,请使用.map
。
此外,如果发生错误,则应调用reject
,以便可以处理Promise
(con.query
回调)的使用者中的错误,否则,当发生错误时,它将永远挂起,而您对此一无所知:
con.query(sql,[req.params.quizId],(err,rows,fields)=>{
if(err) throw err;
Promise.all(rows.map((item) => (
getChoices(item.id)
.then((choices) => ({ ...item, choices }))
)))
.then((response) => {
res.send(response);
})
.catch((err) => {
// handle errors
})
});
function getChoices(questionId) {
const sql='SELECT id,text FROM `question_choices` where question_id=?';
return new Promise((resolve, reject) => {
con.query(sql,[questionId],(err,rows,fields)=>{
if(err) reject(err);
else resolve(rows);
});
});
}