如何规范接口输出协议——Eggjs最佳实践系列(一)

·  阅读 468

本文首发于:kapeter.com/post/32

文章列表:

这是Eggjs最佳实践系列的第二篇文章。


前期调研

在设计之前,先来看一下一份规范的接口输出协议是怎么样的。

{
  code: "-10001",
  message: "The route does not exist, please check whether the route is correct.",
  result: null,
  sysTime: 1620632378967
}
复制代码

命名上可能有所差异,但基本上都是按照以下四个属性:

  • code: 全局唯一的响应码,前端可以根据该响应码进行对应的错误处理;
  • message:响应码(code)的语义化解释;
  • result:用于存放接口数据;
  • sysTime:可选,当前服务器时间,可以与客户端时间进行比对。

封装输出函数

通过调研,我们发现规范的接口输出协议具有统一的格式。我们可以封装一个接口输出函数,来统一输出结果。

我们可以借助Eggjs的框架扩展能力来实现这个函数。

app/extend/response.js文件中,创建两个方法。

'use strict';

module.exports = {
  /**
   * @description
   * @param {*} { data, status }
   */
  success({ data, status }) {
    const { ctx } = this;
    ctx.body = {
      code: '0',
      message: 'success',
      result: data || null,
      sysTime: ctx.helper.now(),
    };
    ctx.status = status || 200;
  },

  /**
   * @description
   * @param {*} { status, code, message, data }
   */
  failure({ status, code, message, data }) {
    const { ctx } = this;
    ctx.body = {
      code: code || '-1',
      message: message || 'no message',
      result: data || null,
      sysTime: ctx.helper.now(),
    };
    ctx.status = status || 200;
  },
};
复制代码

successfailure功能基本一致,前者用于正常响应,code统一为0message统一为success;后者用于错误响应,codemessage需要自行传入。为了前端方便处理,状态码建议全部是使用200(即成功响应)。

现在,我们就可以在控制器中使用这两个函数了。

async index() {
  const { ctx, config } = this;
  ctx.response.failure(config.ERR_TYPE.NOT_EXIST_ROUTE);
}

async test() {
  const { ctx } = this;
  ctx.response.success({ data: ['test', 'test2'] });
}
复制代码

输出结果如下图:

企业咚咚20210510161419.jpg

细心的同学可能还发现了一个小细节,输出系统时间时,使用了一个自行定义的函数now()

这同样是通过框架扩展能力实现的,扩展了helper类。这样就不需要每次去copy代码。

合理的封装可以大大提升开发效率,优化代码结构。

统一管理错误类型

我们已经实现了统一输出协议,是不是这样就够了呢?答案是否定的。设想一下,当系统发展到一定阶段,出现多模块,多人协作的情况时,如果每个人都维护自己的错误响应码(code),就有可能出现code重复使用,不同类型的code无法区分的问题。

为了解决这个问题,就需要在设计之初,对code码进行统一管理。

Eggjs中,一切配置相关的数据都放在config文件夹。

我新建了一个error.js文件,用来专门存放错误配置。这里,通过不同的前缀来区分不同类型的错误。

// config/error.js

module.exports = {
  // 系统错误, -10000级别
  UNKNOWN_ERROR: { code: '-10000', message: 'Internal server error.' }, // 未知错误
  NOT_EXIST_ROUTE: { code: '-10001', message: 'The route does not exist' }, // 路由不存在
  // 上游系统错误 -20000级别
  Up_SYS_TIME_OUT: { code: '-20001', message: 'Upstream system timeout.' }, // 上游系统超时
  // 业务错误,-30000级别
  NOT_LOGIN: { code: '-30001', message: 'Not login.' }, // 未登录
};
复制代码

随后,将这些配置注入到系统配置中去。

// config/config.default.js
const ERR_TYPE = require('./error');

const userConfig = {
  ERR_TYPE,
};
复制代码

需要使用的时候,可以从app.config.ERR_TYPE中获取这些配置,上文已演示这一点。

参考资料

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改