Express 中的中央错误处理
Express 是一个快速、无偏见、极简的 Node.js Web 框架 -文档
无论是使用 Express 还是其他任何语言构建应用程序,错误处理都是不可缺少的例行工作。
使用 Express 或其他框架/库构建 API 端点时,每个用例都需要进行验证检查,并且始终需要向用户返回错误响应。处理这些错误并为每个验证返回响应会变得非常繁琐,并使代码库变得混乱。
让我们考虑以下示例:
const validateUser = async (req, res, next) => {
try {
const { email, password } = req.body
if (!email || !password) {
return res.status(400).json({
status: 'error',
message: 'Missing required email and password fields',
})
}
const user = await db.User.findOne({ where: { email }});
if (!user) {
return res.status(404).json({
status: 'error',
message: 'User with the specified email does not exists',
})
}
next()
} catch (error) {
return res.status(500).json({
status: 'error',
message: 'An error occurred trying to process your request',
})
}
}
看看上面的代码片段,你肯定会同意我的观点:每个检查点都返回错误响应,这看起来已经很乱了。如果你的代码库里只有这些代码,那还好,但当你需要在代码库中的多个方法或函数中重复相同的方法时,问题就出现了。
在我们深入寻找解决方案来改进上面的代码片段之前,让我们先看看这篇文章需要什么:
要求
- NodeJs已安装
- 已安装 npm 或 yarn
- 了解 Nodejs/Express
注意:本文假设读者已具备 NodeJs/Express 的基础知识。因此,部分细节可能会被跳过。
为了继续,请在此处克隆本文使用的存储库。
步骤 1.创建自定义 **Error * 构造函数*
我们需要创建一个自定义 Error 构造函数来扩展JavaScript Error 构造函数。
在你之前克隆的项目中,创建一个名为helpers 的目录。在helpers目录中,创建一个名为error.js的文件。
将下面的代码片段添加到error.js中
class ErrorHandler extends Error {
constructor(statusCode, message) {
super();
this.statusCode = statusCode;
this.message = message;
}
}
module.exports = {
ErrorHandler
}
请注意,我们导出了 ErrorHandler,以便我们可以从index.js文件导入它。
接下来,我们需要创建一个函数来向用户返回格式化的错误响应。
将下面的代码片段添加到error.js
文件中。
const handleError = (err, res) => {
const { statusCode, message } = err;
res.status(statusCode).json({
status: "error",
statusCode,
message
});
};
更新module.exports
块以包含handleError
如下所示的函数:
module.exports = {
ErrorHandler,
handleError
}
步骤 2.创建错误处理中间件
中间件函数是指可以访问请求对象 (req)、响应对象 (res) 以及应用程序请求-响应周期中的下一个中间件函数的函数。
下一个中间件函数通常用名为 next 的变量表示。Express文档
错误处理中间件是一种特殊类型的中间件,与常规中间件不同,它接受四个参数。第一个参数是错误对象。
以下代码片段展示了一个错误处理中间件的示例:
function(err, req, res, next) {
//code goes here
}
在 中index.js
,我们来添加一个错误处理中间件,在此之前,我们先导入handleError
里面的函数index.js
;
该index.js
文件应如下所示:
const express = require('express')
const { handleError } = require('./helpers/error')
const app = express()
app.use(express.json())
const PORT = process.env.PORT || 3000
app.get('/', (req, res) => {
return res.status(200).json('Hello world');
})
app.use((err, req, res, next) => {
handleError(err, res);
});
app.listen(PORT, () => console.log(`server listening at port ${PORT}`))
注意我们如何调用handleError
函数并将错误对象和响应对象传递给它。
注意:错误处理中间件必须是其他中间件和路由中的最后一个,才能正常运行。
现在,在应用程序中任何需要检查错误的地方,只需抛出ErrorHandler
构造函数即可。
现在我们可以应用错误处理机制来重构之前混乱的代码。它应该如下所示:
const validateUser = async (req, res, next) => {
try {
const { email, password } = req.body
if (!email || !password) {
throw new ErrorHandler(404, 'Missing required email and password fields')
}
const user = await db.User.findOne({ where: { email }});
if (!user) {
throw new ErrorHandler(404, 'User with the specified email does not exists')
}
next()
} catch (error) {
next(error)
}
}
注意我们是如何将错误传递给next
上面的函数的。它的作用只是将错误传递给我们在 中定义的错误处理中间件index.js
。
让我们添加一条路由来测试我们刚刚创建的错误处理机制。添加index.js
以下代码片段:
app.get('/error', (req, res) => {
throw new ErrorHandler(500, 'Internal server error');
})
记得在 中导入 ErrorHandler index.js
。它应该如下所示:
const { handleError, ErrorHandler } = require('./helpers/error')
运行 npm start 启动服务器,然后访问路由/error
。您将收到类似如下所示的响应:
{
"status": "error",
"statusCode": 500,
"message": "Internal server error"
}
结论
在本文中,我们确定了 Express 应用程序中需要有一个中央错误处理程序。我们还演示了实现中央错误处理程序所需的步骤。
如果您有任何问题或意见,希望本文能够改进,请通过Twitter联系我。
感谢您的阅读。✌️