【问题标题】:Asynchronous node js "For" loop with database query带有数据库查询的异步节点js“For”循环
【发布时间】:2019-05-27 18:52:55
【问题描述】:

这是为数组中的每个“id”运行查询(SQLite3 数据库)的“for”循环。

qry = "SELECT patients.*, patient_visits.visit_id,patient_visits.patient_id, patient_visits.visitdate, patient_visits.visittime FROM patients LEFT JOIN patient_visits ON patients.id = patient_visits.patient_id "+where+" GROUP BY patients.id ORDER BY patients.id  DESC LIMIT "+limit+" OFFSET "+offset;
db.all(qry, (err, results) => {
    if(err){
        response.error = err;
        res.send(response);
    }else{
        response.patients = patients;
        for (var i = 0; i < patients.length; i++) {
            response.patients[i].check = "false";
            var patient = response.patients[i];
            db.each("SELECT visit_id FROM patient_visits where patient_id='"+patient.id+"' AND visitdate >='"+moment().format('YYYY-MM-DD')+"'", function(err, row) {
                if (row) {
                    response.patients[i].check = "true";
                }
            });
        }
    }
    res.send(response);
});

问题在于 for 循环在查询完成之前继续。有没有办法检查查询是否完成?

【问题讨论】:

  • 使用promise.all

标签: javascript node.js electron desktop-application


【解决方案1】:

这是一种简单的方法,但不推荐。它有可能会多次执行res.send(response);。 我建议你学习如何使用promise

qry = "SELECT patients.*, patient_visits.visit_id,patient_visits.patient_id, patient_visits.visitdate, patient_visits.visittime FROM patients LEFT JOIN patient_visits ON patients.id = patient_visits.patient_id "+where+" GROUP BY patients.id ORDER BY patients.id  DESC LIMIT "+limit+" OFFSET "+offset;
db.all(qry, (err, results) => {
    var loopCount = 0;
    if(err){
        response.error = err;
        res.send(response);
    }else{
        response.patients = patients;
        for (var i = 0; i < patients.length; i++) {
            response.patients[i].check = "false";
            var patient = response.patients[i];
            db.each("SELECT visit_id FROM patient_visits where patient_id='"+patient.id+"' AND visitdate >='"+moment().format('YYYY-MM-DD')+"'", function(err, row) {
                if (row) {
                    response.patients[i].check = "true";
                    loopCount++;
                    if(loopCount == patients.length){
                        res.send(response);
                    }
                }
            });
        }
    }

});

【讨论】:

    【解决方案2】:

    使用foreach 和一个叫做promise 的东西。由于 Nodejs 是异步的,要让它等待查询结果,你必须使用 Promise。

    【讨论】:

      【解决方案3】:

      使用 Promise.all 处理多个异步请求。编写一个新函数从数据库中获取 visit_id。像这样的,

      function getPatientVisitsByVisitId(visitId){
       // return a new promise.
       }
       let promises= [];
       for(var i = 0; i < patients.length; i++){
        patientVisits.push(getPatientVisitsByVisitId(response.patients[i]));
       }
       Promise.all(promises).then((results) => {
       // results will have visit id's.
       })
       .catch((error) => {
        // handle error here
        })
      

      【讨论】:

        【解决方案4】:

        有没有办法检查查询是否完成?

        您可以使用Promise.all() 了解所有异步调用是否已完成。

        'use strict';
        
        function fetchPatients(where, limit, offset) {
          let qry = "SELECT patients.*, patient_visits.visit_id,patient_visits.patient_id, patient_visits.visitdate, patient_visits.visittime FROM patients LEFT JOIN patient_visits ON patients.id = patient_visits.patient_id " + where + " GROUP BY patients.id ORDER BY patients.id  DESC LIMIT " + limit + " OFFSET " + offset;
          return new Promise((resolve, reject) => {
            db.all(qry, (err, patients) => {
              if (err) {
                return reject(err);
              }
              resolve(patients);
            });
          });
        }
        
        function queryVisitsByPatientId(patient) {
          return new Promise((resolve, reject) => {
            patient.check = "false";
            db.each("SELECT visit_id FROM patient_visits where patient_id='" + patient.id + "' AND visitdate >='" + moment().format('YYYY-MM-DD') + "'", function (err, row) {
              if (err) {
                return reject(`Failed for ${patient.id}`);
              }
              if (row) {
                patient.check = "true";
              }
              return resolve(patient);
            });
          });
        }
        
        fetchPatients(where, limit, offset).then(patients => {
        
          let allPatients = patients.map(patient => {
            return queryVisitsByPatientId(patient);
          });
        
          return Promise.all(allPatients);
        }).then(patientDetails => {
          return res.send({
            patients: patientDetails
          });
        }).catch(err => {
          return res.send({
            error: err
          });
        });
        

        【讨论】:

          【解决方案5】:

          请导入异步模块。

          qry = "SELECT patients.*, patient_visits.visit_id,patient_visits.patient_id, patient_visits.visitdate, patient_visits.visittime FROM patients LEFT JOIN patient_visits ON patients.id = patient_visits.patient_id " + where + " GROUP BY patients.id ORDER BY patients.id  DESC LIMIT " + limit + " OFFSET " + offset;
          db.all(qry, (err, results) => {
              if (err) {
                  response.error = err;
                  res.send(response);
              } else {
                  response.patients = patients;
          
                  async.forEachOf(patients, function (patient, key, callback) {
                      db.each("SELECT visit_id FROM patient_visits where patient_id='" + patients[key] + "' AND visitdate >='" + moment().format('YYYY-MM-DD') + "'", function (err, row) {
                          if (row) {
                              response.patients[i].check = "true";
                          }else{
                              callback();
                          }
                      });
                  }, function (error) {
                      if (error) {
                          console.log(error)
                      } else {
                          res.send(response);
                      }
                  })
          
              }
          });
          

          【讨论】:

          • 我已经通过如下查询解决了这个问题,现在不需要使用循环了。我在查询中添加了左连接。 qry = "选择患者。*, patient_visits.visit_id,patient_visits.patient_id, patient_visits.visitdate, patient_visits.visittime FROM patients LEFT JOIN patient_visits ON patients.id = patient_visits.patient_id AND patient_visits.visitdate >= '"+moment().format ('YYYY-MM-DD')+"' "+where+" GROUP BY patients.id ORDER BY patients.id DESC LIMIT "+limit+" OFFSET "+offset;但是谢谢大家的回答,将来也会对我有所帮助。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-11-30
          • 2021-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-11
          相关资源
          最近更新 更多