Express 是一个简洁而灵活的 node.js Web应用框架, 提供一系列强大特性帮助你创建各种Web应用。本文主要介绍如何使用express框架的中间件来实现WebAPI的异常,错误捕获处理。
项目背景知识和程序中已有代码,请参考我的博文Express实现WebAPI之请求实现与调试
错误处理相关类的设计思想是所有API的error类都继承自JS的Error基类,每种错误类型对应一个Http状态码(400到599)本文只列举出了常用的几个错误类型,类图如下所示:
const {StatusCodes, ReasonPhrases} = require("http-status-codes");
class CustomerAPIError extends Error{
constructor(message){
if (!message){
message = ReasonPhrases.INTERNAL_SERVER_ERROR;
}
super(message);
this.statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
}
}
module.exports = CustomerAPIError;
const CustomerAPIError = require("./CustomerApiError");
const {StatusCodes, ReasonPhrases} = require("http-status-codes");
class BadRequestError extends CustomerAPIError{
constructor(message){
if (!message){
message = ReasonPhrases.BAD_REQUEST;
}
super(message);
this.statusCode = StatusCodes.BAD_REQUEST;
}
}
module.exports = BadRequestError;
const CustomerAPIError = require("./CustomerApiError");
const {StatusCodes, ReasonPhrases} = require("http-status-codes");
class UnAuthError extends CustomerAPIError{
constructor(message){
if (!message){
message = ReasonPhrases.UNAUTHORIZED;
}
super(message);
this.statusCode = StatusCodes.UNAUTHORIZED;
}
}
module.exports = UnAuthError;
上述每个错误处理类,对应一个JS文件,都放在项目的error目录下,并增加一个index.js出口文件,导出所有的错误处理类,方便其它代码解构使用,代码如下:
const CustomerAPIError = require("./CustomerApiError");
const BadRequestError = require("./BadRequestError");
const UnAuthError = require("./UnauthError");
module.exports = {
CustomerAPIError, BadRequestError, UnAuthError
};
定义exceptionHandler中间件,用于捕获代码中抛出的异常错误,代码如下:
const {CustomerAPIError} = require("../errors");
const exceptionHandler = async (err,req,res, next) => {
const customerError = new CustomerAPIError();
if (err instanceof CustomerAPIError){
return res.status(err.statusCode).json({
msg: err.message
});
}
return res.status(customerError.statusCode).json({
msg: customerError.message,
err
});
}
module.exports = exceptionHandler;
const exceptionHandler = require("./exceptionHandler");
module.exports = {
exceptionHandler
}
require('dotenv').config({path:'.env'});
const express = require('express');
const app = express();
require("express-async-errors");
const bodyParser = require("body-parser");
const port = process.env.PORT || 5000;
const msgRouter = require("./routes/test/");
const {exceptionHandler} = require('./middlewares')
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.use('/api/v1', msgRouter);
app.use('/api/v1', exceptionHandler);
const start = async () => {
try {
app.listen(port, ()=>{
console.log(`Server is listening on port ${port}...`)
});
} catch (error) {
console.log(error);
}
}
start();
我们在下面Post方法中,增加对表单数据age栏位的验证,该栏位必须是数字,否则抛出异常。代码如下:
const postMsg = async (req,res) => {
const {age,name} = req.body;
const {id} = req.params;
if (isNaN(new Number(age))){
throw new BadRequestError("Age should be number");
}
res.status(StatusCodes.OK).json({
msg : `post request is success ` ,
forms: `form parameter age is ${age} and name is ${name}`,
id:id
});
};
我们使用Thunder Client进行WebAPI的调试
从执行结果可以看出,在表单中,我们的age设定为12p,它并不是一个数字,返回结果符合预期,http状态码是400,错误信息是“Age should be number”
我们定义一个新的未知错误中间件,对于所有的未知的错误,都交给它来处理。让exceptionHandler只处理已知的异常错误。这样便于处理更复杂的场景,以及错误分析,定义有问题的代码。
解耦后的exceptionHandler代码如下:
const {CustomerAPIError} = require("../errors");
const exceptionHandler = async (err,req,res, next) => {
if (err instanceof CustomerAPIError){
return res.status(err.statusCode).json({
msg: err.message
});
}else{
next(err);
}
}
module.exports = exceptionHandler;
未知错误处理代码如下:
const {CustomerAPIError} = require("../errors");
const unkonwnErrorHandler = async (err,req,res, next) => {
if (!!err){
const customerError = new CustomerAPIError();
return res.status(customerError.statusCode).json({
msg: customerError.message,
});
}
}
module.exports = unkonwnErrorHandler;
两个中间件应用顺序如下:
app.use('/api/v1', exceptionHandler);
app.use('/api/v1', unkonwnErrorHandler);
Express实现WebAPI之环境搭建
Express实现WebAPI之请求实现与调试
Express实现WebAPI之错误异常处理