Рефакторинг запросов мангуста

#node.js #mongoose

#node.js #мангуст

Вопрос:

Я использую mongoose довольно много, и, похоже, я не могу обойти «ад обратного вызова» и загрязнять свои запросы обработкой ошибок.

Например, вот маршрут, который у меня есть:

 var homePage = function(req, res) {
        var companyUrl = buildingId = req.params.company

        db.pmModel
            .findOne({ companyUrl: companyUrl })
            .exec(function (err, doc) {
                if (err)
                     return HandleError(req, res, err)

                if( !doc )
                    return NoResult(req, res, {msg: 'Aint there'})

                console.log(doc)

                db.rentalModel
                    .find({ propertyManager: doc.id })
                    .populate('building')
                    .exec(function (err, rentals) {
                        if (err)
                             return HandleError(req, res, err)

                        if( !doc )
                            return NoResult(req, res, {msg: 'Aint there'})

                        console.log(doc)

                        var data = doc.toJSON()

                        data.rentals = rentals

                        res.render('homePage', data)
                    })
            })
    } 
  

мой вопрос: есть ли более краткий способ написать это?

Ответ №1:

Так что, возможно, то, что у вас есть выше, — это всего лишь небольшой пример, но мне не кажется, что в вашем коде происходит слишком много «ада обратного вызова» (на мой взгляд). Тем не менее, вы, безусловно, можете реорганизовать свой код. Просто знайте, что при этом вы можете усложнить понимание или отслеживание с точки зрения обслуживания.

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

Другим решением является преобразование ваших вызовов в отдельные функции и управление потоком по-другому. Популярной библиотекой, помогающей в этом, является async, которая предоставляет множество вспомогательных функций для помощи в асинхронном мире JavaScript. Есть из чего выбирать, но одним из предложений было бы использовать функцию водопада для вашей ситуации (поскольку каждый вызов должен выполняться перед следующим). Тогда это выглядело бы примерно так:

 async.waterfall([
    function(callback){
        findCompany(companyUrl, callback);
    },
    function(id, callback){
        findPropertyManager(id, callback);
    }
], function (err, rentals) {
   res.render(rentals)
});
  

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

Но опять же, код, который вы показали выше, понятен и читаем, и содержит только пару встроенных обратных вызовов. Таким образом, происходит намного меньше работы, и это может упростить отладку позже (если что-то пойдет не так).

Комментарии:

1. Я должен был опубликовать более крупный пример, лол, я пытаюсь обойти ситуации, подобные этой, когда мне нужно перейти к 5 моделям, противоположным 2 выше. Вот где это становится болезненным.

2. @delboud Я могу понять 🙂 Тогда вышеуказанное все равно будет применяться — вы могли бы либо объединить документы (где это возможно), либо использовать что-то вроде асинхронности, чтобы лучше управлять потоком кода. Затем преобразуйте свою логику в отдельные функции, каждая из которых отвечает за запрос mongo, и в результате вызовет обратный вызов либо с ошибкой, либо с результатом.