【问题标题】:render page after for loop is finished node.jsfor循环完成后渲染页面node.js
【发布时间】:2022-02-07 22:18:14
【问题描述】:

我遇到了一个异步问题,我已经在网上关注了很多文章来尝试解决这个问题,但它没有做任何事情。

 async function getNumOfSessionForTrainerClientList(req, res, rows, allowedToAddMoreClients, alertMessage) {
     
      let sessionData2 = []
      var getNumOfSessionForTrainerClientList = "select * from SCHEDULE WHERE CLIENT_USERNAME = ? AND ASSIGNED_TRAINER = ?"
      mysqlconn.connect(async function(err) {
          if (err) {
            console.error('Database connection failed: ' + err.stack);
            return;
          }
        for (var i = 0; i < rows.length; i++) { 
        mysqlconn.query(getNumOfSessionForTrainerClientList, [rows[i].USERNAME, req.session.username], async function(err, sessionData) {
            if (err) {
                console.log(err);
            } else {
                for (var x = 0; x < sessionData.length; x++) {
                    sessionData2.push(sessionData[x].SESSION_STATUS)
                    console.log(sessionData2)
                }


            }
           
        })
}


})
await res.render('trainerclientlist.ejs', {data: rows, trainerFirstName: req.session.firstname, trainerLastName: req.session.lastname, allowedToAddMoreClients: allowedToAddMoreClients, profilePhoto: req.session.profilePhoto, alertMessage: req.session.selectedalertmessage, sessionData: sessionData2})
console.log(sessionData2)

}

发生的情况是console.log(sessionData2) 发生在页面呈现之后,await res.render('trainerclientlist.ejs', {data: rows, trainerFirstName: req.session.firstname, trainerLastName: req.session.lastname, allowedToAddMoreClients: allowedToAddMoreClients, profilePhoto: req.session.profilePhoto, alertMessage: req.session.selectedalertmessage, sessionData: sessionData2})。我该如何解决这个问题?

【问题讨论】:

  • 不要在那里调用,你会在mysql连接完全返回结果后调用它。
  • @BGPHiJACK 但它在代码中的什么位置?
  • 在循环中一遍又一遍地调用查询是非常低效的,不仅是它导致您不同步,而且您正在以超快的速度同步触发循环并且它不会'不在乎查询需要多长时间才能回复。我会问是否有更好的方法来执行查询而不是像那样循环,如果没有,您需要使用队列方法以不同的方式处理此问题,并在完成运行 res.render
  • 哦,好的,很高兴知道,谢谢。基本上我正在做的是在第一次查询完成后调用函数getNumOfSessionForTrainerClientList()。然后我使用结果来做这个查询。我这样做是因为可能有多达 25 个rows[i].USERNAME,所以我觉得我需要一个循环。但是,如果您有任何其他建议,那就太好了
  • 我发了一个帖子来帮助可视化正在发生的事情,哪里可以修复它。至于你的 MySQL 设计/查询,你总是可以更有效地避免这些类型的问题。

标签: javascript mysql node.js


【解决方案1】:

for (var i = 0; i < rows.length; i++) { // I'd avoid this line
// This will force query x-amount of times, 
  mysqlconn.query(getNumOfSessionForTrainerClientList, [rows[i].USERNAME, req.session.username], async function(err, sessionData) {
    if (err) {
      console.log(err);
    } else {
      // this could had been returned 200ms ->5s from when it's called
      for (var x = 0; x < sessionData.length; x++) {
        sessionData2.push(sessionData[x].SESSION_STATUS)
        console.log(sessionData2)
      }
      // I'd make your res.render call here or call for the next query till all are finished and when none left, now call res.render here...
    }

  })
}
// probably took 1-20ms to complete the loop and so sessionData2 is not ready..
console.log(sessionData);
我看到的问题是您围绕查询调用运行一个循环,它不会等待每个回调,而是触发每个查询,并且将来某个时候会收到回调。鉴于这一切发生得很快,您可以想象 MySQL 服务器延迟响应,而正是这使得 sessionData 未定义。如果您将 setTimeout 设置为 5 秒,则应该定义它,因为给了足够的时间(但不要这样做......坏主意)。

您可以进行的最大修复是设置它,这样您就不必遍历 rows.length... 然后您可以在 MySQL 响应时简单地运行 res.render。

【讨论】:

  • 感谢您的帮助。我会像你提到的那样考虑修复它。再次感谢
  • 这里有很多 MySQL 专家,他们很乐意帮助您整理出更有效的方法。
猜你喜欢
  • 2015-06-16
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
相关资源
最近更新 更多