Вызов next внутри вспомогательной функции?

Я пытаюсь настроить простую систему для рендеринга ошибок пользовательского ввода и остановки распространения в экспрессе, вот что у меня получилось:

routingFunction= (req, res, next) {
  //setting up a test in express-validator
  var test = req.assert('access_token', 'required').notEmpty();
  isValid(test, next);
  //non error stuff
}

isValid = (tests, next) => {
    //some more code here, that checks if any errors were found and save tem to the array errors.
    if(errors.length > 0){
        return next(new Error());
    }
};

 //a middleware that catches errors:
 app.use((err, req, res, next) => {
     res.json('error').end();
 });

Моя проблема с этим заключается в том, что он не останавливает распространение, когда я вызываю Next(new Error());, я мог бы вернуть true/false из isValid, а затем вернуть next(new Error()), но это добавило бы много раздувания моим контроллерам. , есть ли лучший способ сделать это из вспомогательной функции?


person Himmators    schedule 16.07.2016    source источник


Ответы (2)


В основном файле маршрута, например. routes/index.js

// Set of func(req, res, next)
let v = require('validator'); // middleware-validators
let user = require('user'); // routes for user 
...
app.get('/smth-route-of-user', v.isTokenSet, v.isEmail, ..., user.get)

In middlewares/validator.js

let v = require('validator-func-list');
...
exports.isTokenSet = function (req, res, next) {
    if (v.isValid(req.body.token))
        next(); // Forwarding to next middleware. In our route next() called v.isEmail
    else
        next(new Error('Token is empty')); // Stop route chain and call error-middleware;
}

exports.isEmail = function (req, res, next) {
... 

Вы можете присоединять валидаторы к одному, например. checkUser() и используйте только один в маршруте.

In middlewares/errorHandler.js

module.exports = function (err, req, res, next) {
    let msg = err.message; // Here we see 'Token is empty';

    if (req.xhr)
         res.json(msg);
    else
         res.render('error_page.html', {message: msg, ...});

    // Here we can call next(err) to forwarding error to next errorHandler. In example below it was errorHandler2.
}

В app.js не забудьте прикрепить error-middleware к приложению.

app.use(require('middlewares/errorHandler'));
app.use(require('middlewares/errorHandler2'));

Если вам нужно собирать ошибки, тогда валидатор должен отправить ошибку в req.errors (или другое поле, как вы хотите) и вызвать next() без ошибок. В промежуточном программном обеспечении рендеринга вы просто проверяете req.errors.length и показываете нормальную страницу или страницу с ошибкой.

person Aikon Mogwai    schedule 17.07.2016
comment
Это в значительной степени, моя настройка, проблема, которая у меня есть, заключается в том, что после next(new Error() и этой функции кажется, что функция isValid возвращает и запускает код //non error stuff, я не хочу этого, так как проверка не прошла . - person Himmators; 17.07.2016

Код после isValid(test, next); всегда выполняется. Код ниже блокирует его, но imho грязный.

routingFunction = (req, res, next) {
  var test = req.assert('access_token', 'required').notEmpty();
  if (!isValid(test, next)) 
      return; // callback called by isValid. It's dust.

  //non error stuff
  ...
  next(); // callback must be called 
}

isValid = (tests, next) => {
    if(errors.length > 0){
        next(new Error());
        return false;
    }
    return true; 
};

Больше лучшего использования, как это

routingFunction = (req, res, next) {
  var test = req.assert('access_token', 'required').notEmpty();
  if (!isValid(test)) 
      return next (new Error('error description'));

  //non error stuff
  ...
  next();
}
person Aikon Mogwai    schedule 17.07.2016