Как перестать получать undefined?

Создал класс с методом getPatients() в котором получаю из базы даных firebase информацию. Вот код:

getPatients() {
        const db = firebase.database();

        let patients = [];

        let refDatabase = db.ref('patient');

        let valuesDatabase = [];
        let valuesNameArray = [];
        let valuesBirthArray = [];
        let valuesAgeArray = [];
        let valuesGenderArray = [];
        let valuesCountryArray = [];
        let valuesStateArray = [];
        let valuesCityArray = [];

        refDatabase.on('value', elem => {
            valuesDatabase = elem.val();

            valuesNameArray = Object.values(valuesDatabase.name);
            valuesAgeArray = Object.values(valuesDatabase.age);
            valuesBirthArray = Object.values(valuesDatabase.birth);
            valuesGenderArray = Object.values(valuesDatabase.gender);
            valuesCountryArray = Object.values(valuesDatabase.country);
            valuesStateArray = Object.values(valuesDatabase.state);
            valuesCityArray = Object.values(valuesDatabase.city);

            for (let i = 0; i < valuesNameArray.length; i++) {
                patients = [...patients, { name: valuesNameArray[i], age: valuesAgeArray[i], birth: valuesBirthArray[i], gender: valuesGenderArray, country: valuesCountryArray[i], state: valuesStateArray[i], city: valuesCityArray[i] }];
            }

            return patients;
        });
    }

И в другом файле я этот метод вызываю:

const newPatient = new PatientService();
console.log(newPatient.getPatients());

Но получаю undefined. Насколько я понимаю причина в том, что моя функция ничего не возвращает. Т.е есть return, но он относится к функции внутри refDatabase. И я не знаю как правильно вернуть результат работы функции, т.к если я напишу return после refDatabase, то получу пустой масив из-за того, что refDatabase работает асинхронно и когда сработает return, то ещё не успеет отработать refDatabase. Я мог бы использовать setTimeout и это будет работать, но это очень плохое решение, т.к искуственно замедляется работа приложения и дальнейшая работа идёт очень нестабильно.

Буду благодарен за идею правильного решения проблемы или за полное её решение.


Ответы (1 шт):

Автор решения: vsemozhebuty

Следуя алгоритму, описанному в этой главе, вы можете промисифицировать свою функцию так:

function getPatients(path) {
  return new Promise((resolve, reject) => {
    const db = firebase.database();

    let patients = [];

    let refDatabase = db.ref('patient');

    let valuesDatabase = [];
    let valuesNameArray = [];
    let valuesBirthArray = [];
    let valuesAgeArray = [];
    let valuesGenderArray = [];
    let valuesCountryArray = [];
    let valuesStateArray = [];
    let valuesCityArray = [];

    refDatabase.on('value', elem => {
        valuesDatabase = elem.val();

        valuesNameArray = Object.values(valuesDatabase.name);
        valuesAgeArray = Object.values(valuesDatabase.age);
        valuesBirthArray = Object.values(valuesDatabase.birth);
        valuesGenderArray = Object.values(valuesDatabase.gender);
        valuesCountryArray = Object.values(valuesDatabase.country);
        valuesStateArray = Object.values(valuesDatabase.state);
        valuesCityArray = Object.values(valuesDatabase.city);

        for (let i = 0; i < valuesNameArray.length; i++) {
            patients = [...patients, { name: valuesNameArray[i], age: valuesAgeArray[i], birth: valuesBirthArray[i], gender: valuesGenderArray, country: valuesCountryArray[i], state: valuesStateArray[i], city: valuesCityArray[i] }];
        }

        resolve(patients);
    });
  });
}

И затем можете вызывать её при помощи await (если вы используете ESM модули с последней версией Node.js, функция-обертка main() не нужна):

(async function main() {
  try {
    const newPatient = new PatientService();
    console.log(await newPatient.getPatients());
  } catch (err) {
    console.error(err);
  }
})();
→ Ссылка