简体   繁体   English

在nodejs中的循环内等待承诺

[英]Wait promises inside loop in nodejs

I know this question may already be asked. 我知道可能已经有人问过这个问题。 But I didn't understand how things are worked.that is why I am creating the new thread. 但是我不明白事情是如何工作的,这就是为什么我要创建新线程。

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);
                }
        })
    })

}

I tried several things but none is worked. 我尝试了几件事,但没有任何效果。 I think for loop didn't wait for the promise to complete and it sends the response directly. 我认为for循环没有等待诺言完成,而是直接发送响应。 Some async problems are happening there. 那里发生了一些异步问题。

I can able to get all questions from database and for each question I need to get corresponding choices that I want. 我可以从数据库中获取所有问题,对于每个问题,我都需要获得所需的相应选择。

something like this 像这样的东西

[{id:'xx', text:'yy',choices:[{id:'c',text:'kk']},etc]

forEach runs synchronously . forEach 同步运行。 You're looking for Promise.all , which accepts an array of Promises , and resolves to an array of the resolved values once all of the Promises resolve. 您正在寻找Promise.all ,它接受Promises数组,并在所有Promises解析后解析为解析值的数组。 To transform your rows array to an array of Promises , use .map . 要将rows数组转换为Promises数组,请使用.map

Also, when there's an error, you should call reject so that you can handle errors in the consumer of the Promise (the con.query callback), otherwise, when there's an error, it'll hang forever without you knowing about it: 另外,当出现错误时,您应该调用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);
    });
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM