用户注册

用户数据表搭建完毕后,我们肯定是需要注册用户的,那么首先我们需要创建一个路由api了。

在根目录:/app/router/v1目录下创建一个user.js文件。

user.js:

javascript
复制代码
const Router = require("koa-router"); const router = new Router({ prefix: "/v1/user" }); const { User } = require(`${process.cwd()}/models/user`); //注册用户 router.post("/register", async (ctx, next) => { }); module.exports = router;

注意:记得在app.js中删除上一节require("./models/user")代码,因为已经不需要了,我们这这里使用了。

假设客户端传来的数据如下:ctx.body

javascript
复制代码
{ email: "1321968423@qq.com", password1: "123456", password2: "123456", nickname: "木灵鱼儿" }

那么我们要对这个参数进行校验

参数校验

通过ctx.body我们可以拿到客户端传过来的数据。为此在校验前我们需要安装Joi

shell
复制代码
yarn add joi --dev

joi如何校验数据?

首先我们需要通过Joi.object()创建一个参数校验对象A,然后通过这个参数校验对象A的validateAsync方法,将ctx.body传入,然后joi就会根据我们的设定进行参数校验,不通过将会抛出Error错误对象。

成功,则是会返回被检验的参数,注意,这个参数可以在校验时改动,比如一个参数首尾代空格,我们可以通过joi将首尾空格去除,然后在存入数据库中。

joi默认是自动创建Error对象的,这个错误最终会被我们全局错误捕获所捕获,但是这个Error并没有我们需要参数,所以,我们需要控制joi的错误对象为我们自定义的错误对象才行,好在这个行为我们是可以控制的。

创建校验失败的错误对象

http-error.js:

javascript
复制代码
//基础错误对象 class HttpError extends Error { constructor(msg = "服务器异常", errorCode = 10000, status = 400) { super(); this.errorCode = errorCode; this.status = status; this.msg = msg; } }; //校验不通过的错误对象 class ValidateError extends HttpError { constructor(msg, errorCode) { super(); this.errorCode = errorCode || 10001; this.status = 200; this.msg = msg || "参数检验不通过!"; } }; module.exports = { HttpError, ValidateError, };

ValidateError 将是我们参数校验不通过所使用的错误对象,他的状态是200,访问是成功地。

创建创建用户校验方法

在utils目录下,创建一个validate目录,里面用于存放我们校验的方法,在validate中创建user.js文件

user.js:

javascript
复制代码
const Joi = require("joi"); const { ValidateError } = require(`${process.cwd()}/core/http-error`); const { User } = require(`${process.cwd()}/models/user`); //验证数据库是否已经有相同邮箱 const isExistSameEmail = async (email) => { const user = await User.findOne({ where: { email } }); //查不到返回null if (user) throw new ValidateError("邮箱已存在!"); return email; //可以在这改变返回值 }; //注册账号 const registerValidate = (data) => { const joiObject = Joi.object({ //最低2位邮箱@后面的内容,例:@io email: Joi.string().email({ minDomainSegments: 2 }) .required().external(isExistSameEmail, "是否存在相同邮箱") .error(new ValidateError("邮箱不合法!")), //password 密码必填 6-32位 password1: Joi.string().trim(true).min(6).max(32).required() .error(new ValidateError("密码必须是1-32位!")), //二次检验密码 password2: Joi.string().valid(Joi.ref("password1")) .error(new ValidateError("两次密码必须相同!")), //昵称 最低2位 nickname: Joi.string().trim(true).pattern(new RegExp("^[^\\s]+$")).min(2) .error(new ValidateError("昵称长度最低2位且不能包含空格!")), }); return joiObject.validateAsync(data); }; module.exports = { registerValidate }

具体用法就自己查看joi的文档了,https://joi.dev/api/?v=17.4.0,目前最新是17版本

其中trim(true)是可以去除参数首尾空格。

external表示自定义异步校验,所以他被安排到了最后校验,所以如果在external中对参数进行操作,其他校验器是拿不到的,正因为他是异步的,所以我们在里面使用异步的请求,比如上面对数据进行查询,如果有相同的email就抛出错误。

external接受两个参数,一个要出触发的函数,另一个是说明文字。

如果是一个比较简单的校验,同步就能完成的,我们可以使用custom的方式,他的用法和external差不多,也是两个参数,函数和说明文字,只是他里面不用使用异步的方法。

开始校验

user.js:

javascript
复制代码
const Router = require("koa-router"); const router = new Router({ prefix: "/v1/user" }); const { User } = require(`${process.cwd()}/models/user`); const { registerValidate } = require(`${process.cwd()}/utils/validate/user`); //注册用户 router.post("/register", async (ctx, next) => { //验证 const { email, password1: password, nickname } = await registerValidate(ctx.request.body); // 验证通过 console.log("验证通过") }); module.exports = router;

当他能往下走的时候,说明验证已经通过了,我们就可以往数据库写入内容,写入内容我们也需要引入对象的模型。

javascript
复制代码
const Router = require("koa-router"); const router = new Router({ prefix: "/v1/user" }); const { User } = require(`${process.cwd()}/models/user`); const { registerValidate } = require(`${process.cwd()}/utils/validate/user`); const { User } = require(`${process.cwd()}/models/user`); //注册用户 router.post("/register", async (ctx, next) => { //验证 const { email, password1: password, nickname } = await registerValidate(ctx.request.body); //验证通过加入数据库 await User.create({ email, password, nickname }); }); module.exports = router;

写入数据后我们还需要返回给前端成功的信息。

成功信息返回

返回信息很多人可能是这样写:

javascript
复制代码
ctx.body = { msg: xxxx, .... }

如果每个接口都这样写是不是太累了,对象的格式都是一样的,返回的一些状态值也是一样的。

我们可以创建一个用于返回成功信息的错误对象,这样就能被全局错误捕获所捕获,然后返回给前端。

于是乎:

http-error.js:

javascript
复制代码
//基础错误对象 class HttpError extends Error { constructor(msg = "服务器异常", errorCode = 10000, status = 400) { super(); this.errorCode = errorCode; this.status = status; this.msg = msg; } }; //校验不通过的错误对象 class ValidateError extends HttpError { constructor(msg, errorCode) { super(); this.errorCode = errorCode || 10001; this.status = 200; this.msg = msg || "参数检验不通过!"; } }; //成功的错误对象 class Success extends HttpError { constructor(msg, errorCode) { super(); this.errorCode = errorCode || 2000; this.status = 201; this.msg = msg || "参数检验不通过!"; } } module.exports = { HttpError, ValidateError, Success };

在路由里面使用:

javascript
复制代码
const Router = require("koa-router"); const router = new Router({ prefix: "/v1/user" }); const { User } = require(`${process.cwd()}/models/user`); const { registerValidate } = require(`${process.cwd()}/utils/validate/user`); const { User } = require(`${process.cwd()}/models/user`); const { Success } = require(`${process.cwd()}/core/http-error`); //注册用户 router.post("/register", async (ctx, next) => { //验证 const { email, password1: password, nickname } = await registerValidate(ctx.request.body); //验证通过加入数据库 await User.create({ email, password, nickname }); throw new Success("账号创建成功!"); }); module.exports = router;

分类: Node 标签: nodekoajoi校验注册信息返回

评论

暂无评论数据

暂无评论数据

目录