Nano Hash - криптовалюты, майнинг, программирование

рендеринг результатов нескольких запросов DB/mongoose в представление в express.js

учитывая асинхронный характер запросов мангуста (или продолжения, или повторения), что вы делаете, когда у вас есть несколько запросов, которые вам нужно сделать перед визуализацией представления?

Например, у вас есть user_id в сеансе, и вы хотите получить некоторую информацию об этом конкретном пользователе через findOne. Но вы также хотите отобразить список недавно вошедших пользователей.

exports.index = function (req, res) {
    var current_user = null

    Player.find({last_logged_in : today()}).exec(function(err, players) {
        if (err) return res.render('500');

        if (req.session.user_id) {
            Player.findOne({_id : req.session.user_id}).exec(function(err, player) {
                if (err) return;
                if (player) {
                    current_user = player
                }
            })
        }

        // here, current_user isn't populated until the callback fires 
        res.render('game/index', { title: 'Battle!',
                   players: players,
                   game_is_full: (players.length >= 6),
                   current_user: current_user
        });
    });
};

Итак, res.render находится в первом обратном вызове запроса, хорошо. Но как насчет ожидания ответа от findOne, чтобы узнать, знаем ли мы этого пользователя? Он вызывается только условно, поэтому я не могу поместить render во внутренний обратный вызов, если только я не продублирую его для любого условия. Не красиво.

Я могу придумать некоторые обходные пути -

  • сделайте его действительно асинхронным и используйте AJAX на стороне клиента, чтобы получить профиль текущего пользователя. Но это кажется больше работы, чем оно того стоит.

  • использовать Q и обещает дождаться разрешения запроса findOne перед рендерингом. Но в некотором смысле это было бы похоже на принудительную блокировку, чтобы заставить ответ ждать моей операции. Не кажется правильным.

  • используйте функцию промежуточного программного обеспечения, чтобы получить информацию о текущем пользователе. Это кажется чище, делает запрос многоразовым. Однако я не уверен, как это сделать, или если это по-прежнему будет проявлять ту же проблему.

Конечно, в более экстремальном случае, если вам нужно сделать дюжину запросов, все может стать ужасно. Итак, каков обычный шаблон с учетом такого типа требований?

06.11.2012

Ответы:


1

Да, это особенно раздражает в асинхронном коде. Что вы можете сделать, так это поместить код, который вам нужно будет продублировать, в локальную функцию, чтобы он оставался СУХИМ:

exports.index = function (req, res) {
    var current_user = null

    Player.find({last_logged_in : today()}).exec(function(err, players) {
        if (err) return res.render('500');

        function render() {
            res.render('game/index', { title: 'Battle!',
                       players: players,
                       game_is_full: (players.length >= 6),
                       current_user: current_user
            });
        }

        if (req.session.user_id) {
            Player.findOne({_id : req.session.user_id}).exec(function(err, player) {
                if (err) return;
                if (player) {
                    current_user = player
                }
                render();
            })
        } else {
            render();
        }
    });
};

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

Что-то типа:

exports.loadUser = function (req, res, next) {
    if (req.session.user_id) {
        Player.findOne({_id : req.session.user_id}).exec(function(err, player) {
            if (err) return;
            if (player) {
                req.player = player
            }
            next();
        })
    } else {
        next();
    }
}

Затем вы настроите свои маршруты для вызова loadUser везде, где вам нужно заполнить req.player, и обработчик маршрута может просто получить информацию об игроке прямо оттуда.

06.11.2012
  • спасибо, вроде все просто. Как насчет использования async.parallel для объединения всех результатов? Я попробовал это, и, похоже, это работает, но интересно, хороший ли это подход. У вас, конечно, гораздо меньше запутанности. 06.11.2012
  • Да, async.parallel здесь не работает. Я обновил свой ответ, включив в него решение промежуточного программного обеспечения, которое, вероятно, лучше подходит для вашего варианта использования. 06.11.2012
  • хорошо, это можно использовать повторно и чище благодаря цепочке с next(). 06.11.2012

  • 2

    В настоящее время вы можете использовать app.param в ExpressJS, чтобы легко установить промежуточное ПО, которое загружает необходимые данные на основе имени параметра в URL-адресе запроса.

    http://expressjs.com/4x/api.html#app.param

    08.10.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..