在节点js中的循环内等待承诺

时间:2018-11-24 06:20:10

标签: javascript node.js angular typescript

我知道可能已经有人问过这个问题。但是我不明白事情是如何工作的,这就是为什么我要创建新线程。

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]

1 个答案:

答案 0 :(得分:2)

forEach同步运行 。您正在寻找Promise.all,它接受​​Promises的数组,并在所有Promises解析后解析为解析值的数组。要将rows数组转换为Promises数组,请使用.map

此外,如果发生错误,则应调用reject,以便可以处理Promisecon.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);
    });
  });
}