在Express中使用async-validator进行数据验证

对用户提交的数据验证一般有两个过程。一是在前端进行初步验证,及时提示用户正确输入数据;二是在后端编程坚持一个原则,永远不要相信用户提交的数据,必须对用户提交的数据进行验证。
async-validator是一个异步的数据验证库,著名的前端UI库element-plus使用它作为表单数据验证工具。它的可定制性很强,提供丰富的配置规则,并且提供promise使用方式,在前端开发中的运用体验不错。如果能在后端也能应用async-validator,将尽可能让前后端的验证行为一致,提高代码可维护性。本文提供一个思路,演示如何在Express应用中使用asycn-validator来验证前端提交的数据。

由于asycn-validator支持TypeScript语言,本示例将使用TypeScript编写。如果想了解如何在Node.js平台搭建TypeScript框架,可以参考此链接:https://blog.youkuaiyun.com/cppandtea/article/details/143569774

一、基本原理

  • Express的错误处理机制。Express框架内部自带了一个默认的错误处理函数,它可以处理各种中间件和路由处理函数产生的错误。如果自定义并注册了一个错误处理中间件函数,那么这个错误处理中间件将会接管默认错误处理函数的行为,从而为程序员提供个性化处理错误的机会。Express规定,自定义错误处理中间件函数必须包含四个参数,即:err,req,res和next,它的TypeScript类型是ErrorRequestHandler。
  • Express产生错误的途径
    • 程序运行过程中产生的错误;
    • 使用throw方法抛出错误;
    • 调用中间件和路由处理函数提供的next函数,并向它传递一个非空的参数。
  • 在Express框架中应用async-validator主要思路
    • 如果async-validator对数据验证失败,它将会返回一个拒绝状态的promise;
    • 我们需要捕获并处理的错误信息就在这个promise中,这个时候就可以对验证结果进行个性化处理;
    • 更进一步,可以在自定义错误中间件中统一处理验证结果,从而优化错误响应机制,便于后期维护。具体方法是,在捕捉到async-validator产生的错误验证结果的时候,抛出错误,自定义错误处理中间件将会捕获到这个错误验证结果。

二、运用过程

1. 安装依赖

npm i async-validator

2. 编写自定义错误处理中间件

在自定义错误处理中间件中统一处理错误,使代码更易于维护。

import { ErrorRequestHandler } from "express";
export const errorHandler: ErrorRequestHandler = (e, req, res, next) => {
  // 如果捕捉到错误,则向前端输出错误,并终止处理流程
  if (e) {
    res.send(e);
    return;
  }
  // 没有捕捉到错误,让程序正常运行
  next();
};

3. 编写数据验证中间件

将async-validator整合到中间件中:

// 导入类型和对象
import Schema, { Rules } from "async-validator";
import { RequestHandler } from "express";
// 定义规则
const descriptor: Rules = {
  name: [
    {
      required: true,
      message: "姓名必须填写",
    },
    {
      max: 30,
      min: 3,
      message: "姓名的长度在3和30之间",
    },
  ],
  age: [
    {
      required: true,
      message: "年龄必须填写",
    },
  ],
};
// 生成验证对象实例
const validator = new Schema(descriptor);
// 定义并导出数据验证中间件
export const itemsPostValidator: RequestHandler = async (req, res, next) => {
  try {
    // 调用验证对象,传入需要验证的数据
    await validator.validate(req.body);
    // 如果没有产生错误,则让程序继续
    next();
  } catch (e) {
    // 产生了错误,使用next函数抛出错误,自定义错误处理中间件将会捕捉到这个错误
    next({ code: 400, msg: e });
  }
};

4. 注册数据验证中间件

一般情况下,只需要对某些有数据提交的路由进行数据验证。编写一个路由模块,注册验证中间件

import express from "express";
// 导入验证中间件
import { itemsPostValidator } from "../middleWares/itemRules";
export const items = express.Router();
items.post("*", itemsPostValidator, (req, res) => {
// 如果验证中间件没有抛出错误,则会执行到这里
// 这里可以执行一些操作,比如将数据保存到数据库等
// 并向前端响应一些数据
  res.send({code:200,msg:'数据已提交',data:req.body});
});

5. 注册路由和自定义错误处理中间件

在应用实例中注册路由和自定义错误处理中间件

import express from "express";
// 导入自定义错误处理中间件
import { errorHandler } from "./middleWares/errorHandler";
// 导入路由模块
import { items } from "./routes/items";
const app = express();
app.use(express.json());
// 注册中间件,否则接收不到前端提交的数据
app.use(express.urlencoded({ extended: true }));
// 注册数据提交路由
app.use("/items", items);
// 在最后一步注册自定义错误处理中间件
app.use(errorHandler);
app.listen(3000, () => {
  console.log("服务已成功启动,监听端口:3000");
});

6. 测试代码

启动服务器程序后,使用接口测试工具向http://localhost:3000/items发送post请求,并附上请求体数据:

{name:'mu88888888888888888888888888888888888'}

以上数据中,name的长度超过30,必填的age字段没有提交。最终,服务器返回了以下数据:

{
	"code": 400,
	"msg": {
		"errors": [
			{
				"message": "姓名的长度在3和30之间",
				"fieldValue": "mu88888888888888888888888888888888888",
				"field": "name"
			},
			{
				"message": "年龄必须填写",
				"field": "age"
			}
		],
		"fields": {
			"name": [
				{
					"message": "姓名的长度在3和30之间",
					"fieldValue": "mu88888888888888888888888888888888888",
					"field": "name"
				}
			],
			"age": [
				{
					"message": "年龄必须填写",
					"field": "age"
				}
			]
		}
	}
}

说明async-validator已经正确工作,并且在自定义的错误处理函数中处理错误验证结果。

三、注意事项

async-validator在前端可以使用type属性限制数据的类型。由于前端向后端提交的数据默认都是string类型的,因此在编写验证规则的时候,最好不要给type属性指定string以外的类型,否则会造成所有数据都会验证失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值