0

Как вернуть результаты Mongoose из метода find?

33

Проблема с возвращением результатов из нескольких запросов в Mongoose

Я пытаюсь отрендерить страницу с результатами из нескольких запросов к базе данных с использованием Mongoose, но не могу понять, как правильно сделать выборку данных.

В документации я нашел следующий способ, который работает:

users.find({}, function(err, docs){
    res.render('profile/profile', {
        users: docs
    });
});

Однако, я бы хотел вернуть результаты из запросов в более удобном для меня формате, чтобы можно было сделать что-то вроде этого:

var a_users = users.find({}); // не работающий пример

Таким образом, у меня будет возможность получить несколько результатов и использовать их для публикации на странице.

Например, я бы хотел сделать что-то вроде этого:

/* не работающий пример */
var a_users = users.find({});
var a_articles = articles.find({});

res.render('profile/profile', {
    users: a_users,
    articles: a_articles
});

Есть ли способ сделать это? Заранее спасибо за помощь!

4 ответ(ов)

0

Вы пытаетесь навязать синхронную парадигму, но это просто не работает. Node.js в основном однопоточный — когда операция ввода-вывода завершена, контекст выполнения возвращается. Управление сигналами осуществляется с помощью колбеков. Это означает, что у вас будут либо вложенные колбеки, именованные функции, либо библиотека управления потоком, чтобы сделать код более читаемым.

Посмотрите на async.parallel:

async.parallel([
   function(cb){
      users.find({}, cb);
   },
   function(cb){
      articles.find({}, cb);
   }
], function(results){
   // results содержит как пользователей, так и статьи
});

Следуя этому подходу, вы сможете выполнять несколько асинхронных операций параллельно, а затем обработать результаты, когда все они завершатся. Это значительно улучшит читаемость и структуру вашего кода.

0

Вы можете использовать функцию freturn, которую вы предоставили, чтобы обрабатывать результаты без необходимости повторного кода в каждой функции. Вот пример перевода вашего вопроса на русский язык в стиле ответа на StackOverflow:


У вас есть функция, которая используется для возврата результата в функции Node. Вы можете использовать следующую реализацию:

function freturn(value, callback) {
    if (callback) {
        return callback(value); 
    }
    return value; 
}

Кроме того, вы можете добавить необязательный параметр callback в сигнатуры всех ваших функций. Это позволит вам легко управлять возвратом значений, предоставляя возможность обработать их через коллбэк, если он передан, или просто вернуть значение напрямую:

function exampleFunction(param, callback) {
    const result = param * 2; // Пример какой-то логики
    return freturn(result, callback);
}

Таким образом, если вы вызовете exampleFunction с коллбэком, то он будет обработан, а если без него, то функция просто вернет значение.

Обеспечив такой подход, вы сможете избежать дублирования кода и сделать свои функции более удобными для использования.

0

Я сталкивался с очень похожей проблемой, но использовал socket.io и доступ к базе данных с клиента. Мой метод получения данных из базы возвращал содержимое базы до того, как данные успевали загрузиться. Поэтому я поделюсь своими находками здесь:

Вот моя функция для получения данных из базы:

// Читаем доски - полная база данных
var readBoards = function() {
    var callback = function() {
        return function(error, data) {
            if (error) {
                console.log("Ошибка: " + error);
            }
            console.log("Доски от сервера (функция): " + data);
        }
    };

    return boards.find({}, callback());
};

А вот мой слушатель событий сокета:

socket.on('getBoards', function() {
    var query = dbConnection.readBoards();
    var promise = query.exec();
    promise.then(function(boards) {
        socket.emit('onGetBoards', boards);
    }).catch(function(err) {
        console.log("Ошибка: " + err);
    });
});

Чтобы решить проблему, мы используем промисы, которые предоставляет Mongoose, и только после того, как данные получены из базы, я отправляю их обратно на клиент с помощью сокета.

На мой взгляд, это довольно эффективный подход.

0

Вы можете достичь желаемого результата с помощью следующего кода. Надеюсь, это вам поможет.

var async = require('async');

// пользовательские импорты
var User = require('../models/user');
var Article = require('../models/article');

var List1Objects = User.find({});
var List2Objects = Article.find({});
var resourcesStack = {
    usersList: List1Objects.exec.bind(List1Objects),
    articlesList: List2Objects.exec.bind(List2Objects),
};

async.parallel(resourcesStack, function (error, resultSet){
    if (error) {
        res.status(500).send(error);
        return;
    }
    res.render('home', resultSet);
});
Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь