Я пишу приложение в NodeJS10 и Mongoose5. Я пишу пользовательскую функцию разбиения на страницы на стороне сервера. Я хочу запустить нумерацию страниц в контроллере для разделения проблем и повторного использования.
У меня есть запрос, чтобы получить данные и вернуть их в обработчик ответа then (). Затем я вызываю пользовательскую функцию разбиения на страницы внутри обработчика then (). Это работает, но меня беспокоят "вложенные" шаблоны then / catch. Я думаю, что это может быть грязно, особенно если требуется дополнительная обработка данных перед возвратом ответа.
Вот «вложенная» структура. Как я могу улучшить это, чтобы оно больше не было вложенным и более читабельным, при этом все еще перехватывая все возможные ошибки и возвращая правильный ответ? Заметьте, что это работает просто отлично, просто шаблон проектирования запутан, и я хочу по возможности избегать «вложенных» операторов then ().
router.get('/:id', (req, res, next) => {
const origin = 'routes/items.js GET /:id';
const id = req.params.id;
items.find({
_id: id
}).then(data => {
uiCtrl.pagination(data, req.query).then((result) => {
res.status(200).send(result);
}).catch((error) => {
console.error(`pagination failed ${error}`);
res.status(500).send(`pagination failed ${error}`);
});
}).catch((error) => {
console.log(`${origin} ${error}`);
res.status(404).send('Not found');
});
});
Вот пользовательская асинхронная функция, вызываемая внутри результата запроса выше.
const uiCtrl = {};
uiCtrl.pagination = async (data, query) => {
// pagination logic here
return data;
}
module.exports = uiCtrl;
2 ответа
Вот переписать, используя обычный async/await
материал:
var data, results;
try {
data = await items.find({_id:id}).toArray();
}
catch (err) {
console.log(`${origin} ${error}`);
res.status(404).send('Not found');
}
try {
results = await uiCtrl.pagination(data, req.query);
}
catch (err) {
console.error(`pagination failed ${error}`);
res.status(500).send(`pagination failed ${error}`);
}
Следует отметить, что, учитывая тот факт, что я ничего не знаю о вашем коде больше, чем то, что я вижу, возможно, есть и другие вещи, которые вы можете сделать, чтобы сделать код лучше читаемым и более легким в использовании (например, отказ от обещания и выполнение что-то значимое с ним вместо того, чтобы бросать исключения). Вам также нужно будет обернуть весь этот код в метод async
, чтобы вы могли использовать ключевое слово await
.
ИЗМЕНИТЬ
Для завершения, учитывая полный код, я начну с его переписывания:
router.get('/:id', async (req, res, next) => {
const origin = 'routes/items.js GET /:id';
const id = req.params.id;
var itemResults, paginationResults;
try {
itemResults = await items.find({_id: id}).toArray();
}
catch (err) {
console.log(`${origin} ${error}`);
res.status(404).send('Not found');
}
try {
paginationResults = await uiCtrl.pagination(data, req.query);
res.status(200).send(result);
}
catch (err) {
console.error(`pagination failed ${error}`);
res.status(500).send(`pagination failed ${error}`);
}
});
Еще одна вещь, которую я бы сделал как своего рода оптимизация или вспомогательное обслуживание, состояла бы в том, чтобы переместить перехват ошибок в один блок catch
и проанализировать ошибку там, чтобы сделать вещи более краткими.
Кроме того, это относится к тому, что называется callback hell
, что очень важно для информации, о которой вы спрашиваете.
Вот переработанное решение, основанное на принятом ответе. Я получил эту ошибку, думаю, это связано с размещением ключевого слова async непосредственно в определении маршрутизатора, например, router.get('/', async (req, res, next)
. Возможно, потому, что в этом формате он не обрабатывается с помощью функции catch или catch.
(node:3564) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3564) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Я получил слегка измененное решение, создал функцию-обертку и вызвал ее с помощью обработчика then (). Спасибо!
router.get('/', (req, res, next) => {
const origin = 'routes/items.js GET /';
async function queryWrapper() {
let data, results;
try {
data = await items.find();
console.log(`data ${data}`);
}
catch (err) {
console.log(`${origin} ${err}`);
}
try {
results = await uiCtrl.pagination(data, req.query);
}
catch (err) {
console.error(`pagination failed ${err}`);
}
if (results) {
return results;
} else {
return false;
}
}
queryWrapper().then((result) => {
res.status(200).send(result);
}).catch((error) => {
console.error(`${error}`);
res.status(500).send(`${error}`);
});
});
Новые вопросы
node.js
Node.js - это неблокирующая асинхронная среда ввода-вывода, основанная на событиях, использующая движок Google V8 JavaScript и библиотеку libuv. Он используется для разработки приложений, которые интенсивно используют возможность запуска JavaScript как на клиенте, так и на стороне сервера, и, следовательно, выигрывают от повторного использования кода и отсутствия переключения контекста.