Правильный способ обработки посылок и ответа сервера
Я пытаюсь улучшить свой код в node.js / sail.js, и я борюсь с ответом сервера в обещаниях.
Когда вы смотрите на первый .then
функция, которую вы можете увидеть, что метод возвращает false
в случае forbidden access
или же notFound
, Затем в следующем .then
функции, которые я должен проверить, если тип возвращаемого значения === false
перейти к разделу и избегать отправки заголовков http дважды. Можно ли это как-то улучшить, чтобы пропустить все следующее .then
методы в случае неудачи? Я могу бросить исключение, чтобы пойти в последнем .catch
но тогда должно быть case
переключаться между всеми возможными состояниями. (т.е. запрещено, serverError или даже не найдено)
Notification.findOne({id: req.param('id')})
.then(function(notification) {
if (!notification) {
res.notFound();
return false;
}
if (notification.triggeredBy != req.session.user.id) {
res.forbidden();
return false;
}
return notification;
})
.then(function(notification) {
if (notification === false) {
return false;
}
return Notification.update(notification.id, actionUtil.parseValues(req));
})
.then(function(notification) {
if (notification === false) {
return false;
}
res.json(notification);
})
.catch(function(err) {
sails.log(err);
res.serverError({message: 'A server error occurred.'});
})
2 ответа
Если бы я это сделал, сначала я разделил логику и функцию приема / отправки. Во-вторых, я указываю список кодов ошибок. И будет так:
NotificationService.js
/*
Listing of error codes: {
* [1] Object not found
* [2] Forbidden
* [3] Server error
}
*/
module.exports = {
nameOfMethod: function(ID, sessionID) {
return new Promise(function(resolve, reject) {
Notification.findOne({ id: ID })
.then(function(notification) {
if (!notification) return reject({ error_code: 1 });
if (notification.triggeredBy !== sessionID) return reject({ error_code: 2 });
Notification.update(notification.id, actionUtil.parseValues(req))
.then(function(notification) {
return resolve(notification); // finally return our notification
})
.catch(function(err) {
sails.log.error(err); // It's good when log is classified. In this case is error
return reject({ message: 'A server error occurred.' });
});
})
.catch(function(err) {
sails.log.error(err);
return reject({ message: 'A server error occurred.' });
});
});
}
};
NotificationController.js
module.exports = {
notifyMe: function(req, res) {
const ID = req.param('id'), sessionID = req.session.user.id;
NotificationService.nameOfMethod(ID, sessionID)
.then(function(notification) {
return res.send(notification);
})
.catch(function(err) {
switch (err.error_code) {
case 1:
return res.notFound(err);
case 2:
return res.forbidden(err);
default:
return res.serverError(err);
}
});
}
};
В случае, когда я использую переключатель, я думаю, что это лучший способ выбрать правильный ответ, но на этот раз я понятия не имею
Посмотрите, как фильтруется .catch()
реализован в Bluebird - это может быть полезно в вашем случае, чтобы выбросить все ошибки, которые вам нужны, но избегайте большого блока switch/case в catch
обработчик:
.catch(
class ErrorClass|function(any error)|Object predicate...,
function(any error) handler
) -> Promise
.caught(
class ErrorClass|function(any error)|Object predicate...,
function(any error) handler
) -> Promise
Это расширение.catch, которое больше работает как catch-предложения в таких языках, как Java или C#. Вместо ручной проверки instanceof или.name === "SomeError", вы можете указать ряд конструкторов ошибок, подходящих для этого обработчика перехвата. Сначала будет обработан обработчик catch, в котором указаны допустимые конструкторы.
Пример:
somePromise.then(function() {
return a.b.c.d();
}).catch(TypeError, function(e) {
//If it is a TypeError, will end up here because
//it is a type error to reference property of undefined
}).catch(ReferenceError, function(e) {
//Will end up here if a was never declared at all
}).catch(function(e) {
//Generic catch-the rest, error wasn't TypeError nor
//ReferenceError
});
Смотрите: http://bluebirdjs.com/docs/api/catch.html
Вместо:
return false;
ты можешь использовать:
return Promise.reject(someReason);
или же:
throw someReason;
и вам не придется проверять эти false
значения - просто используйте (возможно, несколько) catch
обработчики.