Асинхронный узел js цикл «For» с запросом к базе данных - PullRequest
0 голосов
/ 31 декабря 2018

Вот цикл for для выполнения запроса (база данных SQLite3) для каждого «id» в массиве.

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 продолжается до завершения запроса.Есть ли способ проверить, завершился ли запрос?

Ответы [ 5 ]

0 голосов
/ 31 декабря 2018

Просим импортировать асинхронный модуль.

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

    }
});
0 голосов
/ 31 декабря 2018

Есть ли способ проверить, завершился ли запрос?

Вы можете использовать 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
  });
});
0 голосов
/ 31 декабря 2018

Используйте foreach и то, что называется обещаниями.Поскольку Nodejs является асинхронным, для ожидания результатов запроса вы должны использовать обещания.

0 голосов
/ 31 декабря 2018

Используйте 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
  })
0 голосов
/ 31 декабря 2018

Вот простой способ сделать это, но не рекомендуется.Есть вероятность, что он будет выполнен res.send(response); несколько раз.Я предлагаю вам научиться использовать обещание .

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

});
...