mongoose Node.js + Express中使用promise处理错误

mwkjh3gx  于 2023-04-21  发布在  Go
关注(0)|答案(2)|浏览(154)

使用Node.js + Express(4)+ Mongoose(使用promise而不是回调),我无法理清如何整理我的错误处理。
我得到的(相当简单)是:

app.get('/xxx/:id', function(request, response) {
    Xxx.findById(request.params.id).exec()
        .then(function(xxx) {
            if (xxx == null) throw Error('Xxx '+request.params.id+' not found');
            response.send('Found xxx '+request.params.id);
        })
        .then(null, function(error) { // promise rejected
            switch (error.name) {
                case 'Error':
                    response.status(404).send(error.message); // xxx not found
                    break;
                case 'CastError':
                    response.status(404).send('Invalid id '+request.params.id);
                    break;
                default:
                    response.status(500).send(error.message);
                    break;
            }
        });
});

在这里,在'promise rejected'部分的开关中,Error是我自己为找不到的潜在有效id抛出的错误,CastError是Mongoose为无效id抛出的 Cast to ObjectId failed,并且500错误可以例如通过将throw Error()错误输入为throw Err()(导致 *ReferenceError:Err未定义 *)。
但就像这样,我的每一条路线都有这个巨大的笨拙的开关来处理不同的错误。
我如何集中错误处理?交换机是否可以以某种方式隐藏在中间件中?
(我确实希望我可以在'promise rejected'块中使用throw error;重新抛出,但我无法使其工作)。

csga3l58

csga3l581#

我会创建中间件来处理错误。使用next()处理404s。使用next(err)处理其他错误。

app.get('/xxx/:id', function(req, res, next) {
  Xxx.findById(req.params.id).exec()
    .then(function(xxx) {
      if (xxx == null) return next(); // Not found
      return res.send('Found xxx '+request.params.id);
    })
    .then(null, function(err) {
      return next(err);
    });
});

404处理器

app.use(function(req, res) {
  return res.send('404');
});

错误处理程序

app.use(function(err, req, res) {
  switch (err.name) {
    case 'CastError':
      res.status(400); // Bad Request
      return res.send('400');
    default:
      res.status(500); // Internal server error
      return res.send('500');
  }
});

你可以通过发送一个JSON响应来改善这一点,比如:

return res.json({
  status: 'OK',
  result: someResult
});

return res.json({
  status: 'error',
  message: err
});
piztneat

piztneat2#

我最近需要做错误处理.所以,经历了这么多的资源,终于想出了这个.我们将创建一个custom Error classErrorHandler middleware.自定义错误类用于动态发送其他细节,如statusCode沿着errMsg.而且,中间件用于集中处理所有错误一次,基本上控制台完整的错误,并发送错误响应.
1.创建自定义Err

class Err extends Error {
   statusCode = 500;
   name = "InternalError";
   err = "Error";

   constructor(message, options = {}) {
     super(message);

     for (const [key, value] of Object.entries(options)) {
        this[key] = value;
     }
   }
}

Err类接受以下内容,而内置的Error类只接受message

  • message:您想向客户展示的内容
  • options:它可以包括与错误相关的附加信息,如
  • err(实际错误)
  • name(自定义/实际错误名称)
  • statusCode(如400、404等)

1.创建中间件ErrorHandler

const errorHandler = (err, req, res, next) => {
   console.error(err);

   let errStatus = err.statusCode || 500; 
   let errMsg = err.message;

   //handling some basic mongodb error
   if(err.name === 'CastError') {
     errMsg = `Resource not found. Invalid: ${err.path}`;
     errStatus = 400;
   } else if(err.name === 'ValidationError') {
     errMsg = `Invalid input entered: ${Object.values(err.errors).map(e => e.message)}`;
     errStatus = 400;
   } else if(err.code === 11000) {
     errMsg = `Duplicate ${Object.keys(err.keyValues)} entered`;
     errStatus = 403;
   }
   //you can handle many more such in-built or basic errors like related to jwt, etc

   return res.status(errStatus).json({
     success: false,
     status: errStatus,
     message: errMsg,
     stack: process.env.ENV === 'DEV' ? err.stack : {}
   })
}

现在,错误处理很容易。

  • 每当我们想要抛出一个自定义错误时,我们可以这样做
const err = throw new Err("Leaderboard not exist for this quiz", {
    err: "RedisError", 
    name: "EmptySetError", 
    statusCode: 422
 });

[* 注意:不需要发送所有选项,如果需要,您可以只发送statusCode。*]

  • 或者如果我们从try... catch块中捕获错误
try {
   //do your work like await call
 } catch (err) {

 }

我们可以像这样修改控制器

const ctrl = (req, res, next) => {
   //err is either custom or we are catching from try...catch
   next(err);
}

我们将在index.js文件中所有路由的最后添加此中间件。

app.routes....
app.use(ErrorHandler);

相关问题