Как использовать промежуточное программное обеспечение Express Error для моего случая? - PullRequest
0 голосов
/ 03 февраля 2019

Я использую промежуточное ПО маршрутизатора, чтобы проверить, действителен ли запрос или нет.Кроме того, я использую глобальное промежуточное программное обеспечение обработчика ошибок в конце server.js для перехвата и обработки всех ошибок.

Внутри маршрутизатора я сталкиваюсь с проблемой реализации этого.Следующий код ясно излагает проблему.

Ошибка связующего ПО errorHandler.js

module.exports = function(err, req, res, next) {
    //some logic
    return res.status(400 or 500).json({err});
};

My server.js (короткая версия)

const express = require('express');
const app = express();

app.use('/account/:accid/users', userRouteHandler);

const errorHandler = require('PATH to errorHandler.js file');
app.use(errorHandler);

app.listen(3000, () => console.log(`Example app listening on port 3000!`));

файл userRouteHandler

var express = require('express');
var router = express.Router({ mergeParams: true });
router.use(express.json());

// middleware to use for all requests
router.use(function(req, res, next) {

  /**** PROBLEM / CONFUSION ****/

  checkIfAccountIdExists(req.params.accid) //if exists resolve(count) else reject(new Error)
    .then(next)   //I want to allow calling the get if it exists
    .catch(next); //for error it should call the global error handler
});

router
  .get('/', function(req,res,next){
    console.log("entering here"); 
    findAllTheUsers({accid:req.params.accid})
      .then(users=>res.status(200).json(users);
      .catch(err=>next(err)); //ensure it can call the global error handler
  });

Код, всегда вызывающий маршрут get.Что касается обоих, я звоню next ().Если я вызываю next () только внутри then (), мой глобальный обработчик ошибок будет пропущен при возникновении любой ошибки.

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

Как мне этого добиться?

1 Ответ

0 голосов
/ 03 февраля 2019

Не зная поведения вашей функции checkIfAccountIdExists, я предполагаю, что она возвращает обещание, которое всегда разрешается с false|undefined|null;что-то вроде этого:

checkIfAccountIdExists(id).then((exists) => console.log(exists));
// outputs "false" or "undefined" or "null"

Это мое предположение, потому что иначе ваш .get('/') маршрут даже не должен войти, учитывая, как работает next().

Понимание next():

Звонок next() (к позору Экспресса) всегда сбивал с толку, не имея глубоких знаний об этом.В основном это работает тремя способами:

  • next() (без аргументов) -> передать выполнение следующим обратным вызовам на маршруте
  • next('route') (строка 'route' аргумент) -> обойти любые оставшиеся обратные вызовы в маршруте (переходит на любые маршруты, которые следуют)
  • next(err) (любые другие параметры достоверности,кроме 'route') -> вызывает обработчики ошибок.

В вашем конкретном случае я предполагаю, что checkIfAccountIdExists() решает с false|undefined|null, по существу вызывая next(err) подпись, но потому что err не соответствует действительности, он рассматривается как подпись next(), переходя к обратному вызову следующего маршрута.Я бы проверил здравый смысл checkIfAccountIdExists() для этого.

Использование next() с Обещаниями

При использовании Обещаний важно помнить, что ваш первый аргумент .then() (что означает ваш выполнение обработчик) всегда будет получать параметр !

promise.then(callback);

function callback() {
  console.log(arguments.length); // ALWAYS 1
}

По этой причине вам всегда следует избегать установки next() в качестве обработчика выполнения для обещаний.В противном случае, как только ваш checkIfAccountIdExists() решит с помощью true, он фактически вызовет next(err) подпись!

Всегда пишите: promise.then(() => next()) вместо promise.then(next), чтобы убедиться, что вы звоните nextбез аргументов.

Однако написание promise.catch(next) нормально, потому что это то же самое, что и promise.catch((err) => next(err))

Чуть больше информации об обещаниях

Кроме того, обещания (thenables) допускает два аргумента .then(), один из которых является обработчиком выполнения, а другой - обработчиком отклонения.Пример: promise.then(onFulfillment, onRejection), что аналогично вызову promise.then(onFulfillment).catch(onRejection) , за исключением того, как обнаруживаются ошибки!

  • Для .then(onFulfillment, onRejection) любые ошибки, которые выбрасываются внутри onFulfillment, никогда не бываютonRejection.
  • Для .then(onFulfillment).catch(onRejection) любые ошибки, возникающие внутри onFulfillment, также обнаруживаются onRejection

В вашем случае это означает, что вы можете безопаснонапишите

checkIfAccountIdExists.then(() => next(), next);

, потому что следующий маршрут (onFulfillment arg) также будет обрабатывать ошибки. Примечание: ошибки внутри синхронного кода будут обнаружены экспрессом.

Дополнительная информация:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...