0

Как сделать синхронный запрос к базе MongoDB?

Есть код который подключается к базе и берет из нее выборку и он как бы отрабатывает, но в переменной allNews, вместо данных бывает undefined.

Так понимаю проблема в collection.each((err, item){}), тк он ведет себя как то асинхронно (сначала выводится "Цикл отработал", а потом "работа в цикле")
Если есть другие варианты (более простые) как можно сделать синхронный запрос, буду рад почитать.

Если будет нужна какая-либо еще информация касаемо вопроса, дам.
P.S. Первый проект на Mongo, не серчайте :P

// Подключаемся к БД и берем выборку
let connectDB = async() => {
    let queryProm = new Promise((resolve, reject) => {
        let allNews = [];
        client.connect(err => {
            assert.equal(null, err);
            let db = client.db(dbName);
            let collection = db.collection("news").find({title: {$exists: true}}, {_id: 0});

            collection.each((err, item) => {
                if (item !== null) {
                    console.log("Работа в цикле");
                    allNews.push(item);
                };
            });
            console.log("Цикл отработал");

            resolve(allNews);
            client.close();
        });
    });

    return (await queryProm);
}

// После получения выборки что-нибудь делаем
connectDB().then((data) => {
    console.log( data );
});
  • 1
    Нужно учится работать в асинхронном коде, а не переводить его в синхронный. – Stepan Kasyanenko Dec 05 '19 at 07:37
  • @StepanKasyanenko Нужно сделать так, чтобы при открытии страницы шел запрос к базе и оттуда брались данные (в данном случае все новости), если сделаю асинхронно, то страница может загрузиться без новостей или что то не понимаю?) – Frog Frogov Dec 05 '19 at 07:44
  • Завист от того, где и КАК вы этот код вызываете. – Stepan Kasyanenko Dec 05 '19 at 07:50
  • @StepanKasyanenko Есть модуль работы с mongo. https://github.com/DarkKeksik/bootstrap-learn/blob/master/template/serverJS/mongoConfig.js

    Результат которого импортируется в главный файл сервера (сервер на express) https://github.com/DarkKeksik/bootstrap-learn/blob/master/index.js

    В текущем решении данные с сервера запрашиваются 1 раз после запуска сервера, мне нужно сделать так, чтобы каждый раз как пользователь запрашивает страницу из БД брались данные и выводились, поэтому и хочу сделать синхронный запрос к базе, мол пока данные не запросятся, страница не будет отдана.

    – Frog Frogov Dec 06 '19 at 00:11
  • @StepanKasyanenko Хотя наверное можно сделать API для работы с БД к которому аяксом будет обращаться JS и брать данные, тем самым избавиться синхронности (правда придется прелойдер и клиентскую логику делать на аяксы) – Frog Frogov Dec 06 '19 at 00:20
  • 1
    Вы решаете сам когда отдавать страницу, вы для этого вызываете метод специальный. Вызов этого метода нужно перенести после того, как все данные получены. – Stepan Kasyanenko Dec 06 '19 at 06:24
  • @StepanKasyanenko Понимаю что нужно сделать запрос к БД, а после рендер страницы, но collection.each() работает асинхронно, то есть console.log("Цикл отработал"); выполниться до момента выполнения цикла.

    Возможно как то не так передаю суть вопроса, в любом случае спасибо за попытку ответить.

    – Frog Frogov Dec 06 '19 at 07:05
  • Покажите код, в котором вы отрисовываете данные – Stepan Kasyanenko Dec 06 '19 at 07:48
  • @StepanKasyanenko https://github.com/DarkKeksik/bootstrap-learn/blob/master/template/serverJS/mongoConfig.js - запрос данных https://github.com/DarkKeksik/bootstrap-learn/blob/master/index.js - отрисовка – Frog Frogov Dec 06 '19 at 08:11

1 Answers1

0

Заменил метод each на forEach (ссылка на док. ниже).
https://docs.mongodb.com/manual/reference/method/cursor.forEach/#example

На вход этого метода передаются 2 функции:

  1. Функция, которая возвращает элемент коллекции
  2. Функция, которая возвращает, либо null (завершение цикла), либо информацию об ошибке.

Пример:

collection.forEach((item) => {
    console.log(`Элемент цикла: ${item}`);
}, (end) => {
    console.log(`
        Цикл кончился (${end}) \n
        Сюда мы и передаем success() \n
        для синхронного выполнения функции
    `);
});

collection - коллекция из базы, в моем случае news
let collection = db.collection("news").find({title: {$exists: true}}, {_id: 0});