Skip to content

统一规范

异常处理

一般异常 都是全局处理

先写工具类

  • app/exception文件夹 新建一个http.js文件
js
class HttpException extends Error {
  constructor(
    code = 50000,
    message = "服务器异常",
    stack = null,
    httpCode = 500
  ) {
    super();
    this.code = code;
    // 自定义状态码
    this.msg = message;
    // 自定义返回消息
    this.stack = stack;
    // 自定义返回数据
    this.httpCode = httpCode;
    // http状态码
  }
}
module.exports = HttpException;

写中间件

  • app/middleware文件夹 新建一个error.js文件
js
const HttpException = require("../exception/http");
module.exports = () => {
  return async function errorHandler(ctx, next) {
    const method = ctx.request.method;
    // 当请求方法为OPTIONS,通常为axios做验证请求,直接响应httpStatus204 no content即可
    if (method === "OPTIONS") {
      ctx.status = 204;
      return;
    }
    try {
      // 在这里捕获程序中的异常
      await next();
      // 404 页面就自己定义
      if (ctx.status === 404 && !ctx.body) {
        console.log(ctx);
        if (ctx.request.header["content-type"]) {
          ctx.body = { code: 404, msg: "接口不存在", data: "" };
        } else {
          // 跳转到404页面
          ctx.redirect("/");
        }
      }
    } catch (err) {
      console.log(err);
      // 判断异常是不是自定义异常
      if (err instanceof HttpException) {
        ctx.status = err.httpCode;
        console.log(err.httpCode);
        ctx.body = { code: err.code, msg: err.msg, data: err.stack };
        return;
      }
      // ... 其他异常处理,例如egg参数校验异常,可以在这里处理 // 最后其他异常统一处理
      ctx.status = 500;
      ctx.body = {
        code: 500,
        msg: err.message || "服务器异常",
        data: err.stack,
      };
    }
  };
};

挂载到全局

  • config/config.default.js文件中添加
js
config.middleware = ["error"];

返回格式

继承

  • 在 controller 文件夹中新建一个base.js文件作为基类
js
"use strict";

const Controller = require("egg").Controller;

class ResponsedataController extends Controller {
  async response(data = null, message = "success", code = 200) {
    const { ctx } = this;
    ctx.status = 200;
    ctx.body = {
      code,
      message,
      data,
    };
  }
}

module.exports = ResponsedataController;
  • 在其他 controller 文件中继承
js
"use strict";

const Controller = require("egg").Controller;
const Base = require("../controller/base");

class HomeController extends Base {
  async index() {
    const { ctx } = this;
    this.response(1, "成功", 200);
  }
}

module.exports = HomeController;

静态类

  • 在 utils 文件夹中新建一个tool.js文件
js
class ResponsedataController {
  static async succss(data = null, message = "success", code = 200) {
    return {
      code,
      message,
      data,
    };
  }
}

module.exports = ResponsedataController;
  • 在其他 controller 文件中调用
js
"use strict";

const Controller = require("egg").Controller;
const Tool = require("../utils/tool");

class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    ctx.body = Tool.succss(1, "成功", 200);
  }
}

module.exports = HomeController;

参数校验

安装

bash

npm i egg-validate -S

配置

  • config/plugin.js文件中添加
js
// 验证插件
exports.validate = {
  enable: true,
  package: "egg-validate",
};
  • config/config.default.js中写入
js
// 验证配置
config.validate = {
  // 配置项
  // 配置参数校验器,基于parameter
  convert: false, // 对参数可以使用 convertType 规则进行类型转换,类似数字666会转换成字符
  // validateRoot: false,   // 限制被验证值必须是一个对象。
  widelyUndefined: true, // 开启后,会把空字符串,NaN,null 这些转成 undefined,将这些异常的数据进行了统一,方便后续处理。
};

使用

  • 控制器里面调用
js
const BaseController = require("../base/base");
class ValidateController extends BaseController {
  // 默认post
  async post1() {
    const { ctx, app } = this;
    // 不执行了
    const errors = app.validator.validate(
      {
        username: { type: "string", required: true },
        password: { type: "string", required: true, min: 6, max: 10 },
      },
      ctx.request.body
    );
    if (errors) {
      ctx.body = {
        status: 200,
        msg: errors,
      };
    } else {
      const data = "通过了12121";
      this.response(data, "通过了", 5000);
      // throw new NotFoundException("没有找到数据");
    }
  }
  // 自定义用户名规则
  async post2() {
    const { ctx, app } = this;
    // 校验用户名是否正确
    // 自定义post
    app.validator.addRule("userName", (rule, value) => {
      // value就是待检验的数据
      if (/^\d+$/.test(value)) {
        return "用户名应该是字符串";
      } else if (value.length < 3 || value.length > 10) {
        return "用户名的长度应该在3-10之间";
      }
    });

    const errors = app.validator.validate(
      {
        username: { type: "userName" },
        password: { type: "string", required: true },
      },
      ctx.request.body
    );
    if (errors) {
      ctx.body = {
        status: 200,
        msg: errors,
      };
    } else {
      ctx.body = "验证通过";
    }
  }
  async get1() {
    // 默认自由get
    const { ctx, app } = this;
    const errors = app.validator.validate(
      {
        username: { type: "string", required: true },
        password: { type: "string", required: true },
      },
      ctx.request.query
    );
    if (errors) {
      ctx.body = {
        status: 200,
        msg: errors,
      };
    } else {
      ctx.body = "验证通过";
    }
  }
  async get2() {
    const { ctx, app } = this;
    // 自定义 严格get
    // 校验用户名是否正确
    app.validator.addRule("userName", (rule, value) => {
      // value就是待检验的数据
      if (/^\d+$/.test(value)) {
        return "用户名应该是字符串";
      } else if (value.length < 3 || value.length > 10) {
        return "用户名的长度应该在3-10之间";
      }
    });

    const errors = app.validator.validate(
      {
        username: { type: "userName" },
        password: { type: "string", required: true },
      },
      ctx.params
    );

    if (errors) {
      ctx.body = {
        status: 200,
        msg: errors,
      };
    } else {
      ctx.body = "验证通过";
    }
  }
}

module.exports = ValidateController;
  • 路由
js
module.exports = (app) => {
  const { router, controller } = app;
  // router
  const validateRouter = router.namespace("/validate");
  validateRouter.post("/post1", controller.validate.validate.post1);
  validateRouter.post("/post2", controller.validate.validate.post2);
  validateRouter.get("/get1", controller.validate.validate.get1);
  validateRouter.get(
    "/get2/:username/:password",
    controller.validate.validate.get2
  );
};
  • 调用
bash
http://127.0.0.1:7001/validate/get1?username=admin&password=admin
http://127.0.0.1:7001/validate/get2/admin/123456
http://127.0.0.1:7001/validate/post1/
http://127.0.0.1:7001/validate/post2/