Невозможно вернуть данные, полученные из mongodb - PullRequest
0 голосов
/ 05 мая 2020

Я могу успешно извлечь все данные, хранящиеся в коллекции под названием «темы», используя find () с курсором и foreach. Однако, когда я пытаюсь установить полученную информацию для вызова переменной «data» и отправить ее обратно на страницу, он всегда отображает пустой массив.

Как я могу это исправить?

app.get('/api/get_topics', (req, res)=>{
    let data = [];
    MongoClient.connect(url, (err, db)=>{
        const dbo = db.db('adoption');
        let cursor = dbo.collection('topics').find();
        cursor.forEach((el)=>{
            const obj = {
                img     : el.img,
                title   : el.title,
                content : el.content
            }
            data.push(obj);
        });
        db.close();
    });
    res.json(data); // [] ---> always empty
    res.end();
});

Ответы [ 4 ]

0 голосов
/ 05 мая 2020

MongoClient.connect(url, callback) ...

  • callback (функция) - это будет вызвано после выполнения этого метода. Первый параметр будет содержать объект Error, если произошла ошибка, или null в противном случае. Второй параметр будет содержать инициализированный объект db или null, если произошла ошибка. (https://mongodb.github.io/node-mongodb-native/api-generated/mongoclient.html)

Это намекает на то, что connect () fn c является функцией asyn c. Отсюда res. json (данные); Отправить(); будет выполняться до того, как будет вызван обратный вызов функции подключения, в которой вы заполняете свой массив.

0 голосов
/ 05 мая 2020

Вам необходимо вернуть данные после того, как ваше соединение с базой данных будет выполнено. Перед закрытием соединения и после вашего forEach: поскольку "forEach" является синхронизатором и блокирует событие l oop

app.get('/api/get_topics', (req, res)=>{
    let data = [];
    MongoClient.connect(url, (err, db)=>{
        const dbo = db.db('adoption');
        let cursor = dbo.collection('topics').find();
        cursor.forEach((el)=>{
            const obj = {
                img     : el.img,
                title   : el.title,
                content : el.content
            }
            data.push(obj);
        });
        res.json(data);
        res.end();
        db.close();
    });

});

Примечание: вам следует создавать глобальное соединение, а не для каждого запроса. Соединение можно использовать повторно.

0 голосов
/ 05 мая 2020

Причина пустого data в том, что MongoClient.connect() является асинхронной функцией, то есть код не ожидает вашего обратного вызова для sh содержимого вашего массива data перед установкой данных ответа.

Как отмечали другие, вы можете установить и завершить свой ответ в своем обратном вызове, но я скептически отношусь к тому, что это сработает. Другой подход - использовать метод async/await . Вы можете увидеть это использование из официальных документов MongoDB .

Кроме того, я считаю, что вы можете опустить res.end() или переместить его в ловушку.

Например:

app.get('/api/get_topics', (async (req, res) => {
    try {
        let data = [];
        const db = await MongoClient.connect(url);
        const dbo = db.db('adoption');
        const cursor = dbo.collection('topics').find();
        cursor.forEach((el)=>{
            const obj = {
                img     : el.img,
                title   : el.title,
                content : el.content
            }
            data.push(obj);
        });
        db.close();
        res.json(data);
    } catch (err) {
        // Handle an error here...
        console.log(err);
        res.end();
    }
}));
0 голосов
/ 05 мая 2020

попробуйте это

app.get('/api/get_topics', (req, res)=>{
    let data = [];
    MongoClient.connect(url, (err, db)=>{
        const dbo = db.db('adoption');
        let cursor = dbo.collection('topics').find();
        cursor.forEach((el)=>{
            const obj = {
                img     : el.img,
                title   : el.title,
                content : el.content
            }
            data.push(obj);
        });
        db.close();
        res.json(data); // [] ---> always empty
        res.end();
    });
});
...