• 腾讯抢金达人项目中的前后端协作


    在前后端的协作过程中,通常都是并行开发的状态,那么在后端接口还没有开发完毕时,前端的业务逻辑工作就很难展开。因此也就有很多模拟接口数据的方式,这些方式各有个的优缺点:

    • 直接在代码中模拟接口数据:侵入业务逻辑,在后期需要删除这些模拟数据;
    • fiddler 替换文件:页面接口比较多时,需要替换的文件比较多;
    • fs 模块读取 json 文件:若是长列表的话,需要造的数据很多;
    • mockjs:避免上述方式的缺点,但无法校验参数是否缺失;
    • service worker:基于 service worker 可以拦截前端的请求,并构建假数据返回,但无法拦截 node 端发起的请求;
    方式 校验参数合法性 切换环境方便 前后端请求均可 不修改业务代码 模拟数据方便
    直接在业务代码
    中写接口数据
    fiddler 替换文件 yes
    fs 读取 json 文件 yes yes
    mockjs yes yes yes
    sw yes

    我们理想的状态是:

    1. 提前校验请求接口中参数的合法性,是否缺失某些参数等;
    2. 切换环境方便,既可以使用模拟数据,也可以使用测试环境中的数据,同时也可以用正式环境中的数据进行检验;
    3. 可以拦截前后端均发起的请求,并尽量少的修改业务代码;
    4. 生成的模拟数据方便,假如接口中要返回前 1000 名用户的数据,总不能在 json 文件中写 1000 条数据;

    上面的这几种方式,在我们抢金达人项目中,均不适用,或者对原有逻辑改动太大,或者使用起来不方便。这里我根据我们项目的需要,基于 mockjs 并与 express 的结合,实现了一套模拟数据的方法。

    1. 模拟数据并校验参数的合法性

    把接口的数据全部写在 json 文件,然后通过 fs 模块进行读取的这种方式,在构造大量数据时非常不方便。因此我们基于 mockjs 来实现模拟的数据,几行代码就能实现排行榜等大量的模拟数据,同时,也可以模拟一些稍微极端的情况,例如用户的昵称长度过长等,这些数据在测试环境一般很少能遇到,或者在后端接口模拟的成本也会比较高。

    // rank-person.js
    Mock.mock({
      "rank|1000": [
        {
          "no|+1": 1,
          uin: () => Mock.Random.string(32),
          nick: () => Mock.Random.string(1, 20),
          face: () => faces[Mock.Random.integer(0, 3)],
          region: "INVALID",
          title: "初露锋芒",
          level: () => Mock.Random.integer(1, 20),
          score: () => Mock.Random.integer(1, 2000),
          winPercent: 86
        }
      ]
    });
    

    但是,纯基于 mockjs 数据的方式,我们无法提现获知接口参数的异常。当我们在匹配到接口请求后就返回数据,会降低对参数的敏感度。这里,我对配置文件进行改造,当前接口中需要的参数提前设定好,类似于 jQuery.validate 中的设定。

    这里我们的排行榜接口里有个last参数,0 表示是本周的数据,1 表示是上周的数据:

    module.exports = {
      params: {
        last: {
          required: true, // 是否必须
          type: "number", // 参数的类型
          defaults: 0, // 默认值
          min: 0, // 最小值
          max: 1 // 最大值等
        }
      }
    };
    

    当 mock server 接收到请求后,会先校验参数的合法性,若参数不合法直接返回。其实我们排行榜的 last 参数不是必传项,不传时即默认是 0,但我们在这里测试时改为必传,只要不传 last 参数即为参数不合法:

    mock校验参数-蚊子的博客

    当参数校验通过后,才会返回后面模拟的数据:

    mock模拟的数据-蚊子的博客

    2. 数据环境的切换

    我们在上面的图中可以看到,当 mock 字段为"mock"时,读取模拟的数据,是不是一定要加一个 mock="mock"的参数才能去读模拟的数据呢?

    这个要看咱们项目到什么状态了,当项目还在前提开发阶段时,大部分接口都还没有完成,这里我们可以将接口默认指向到模拟数据,mock="testing"时就指向到测试环境的接口;当项目已稳定上线了,在迭代更新的阶段时,大部分接口已经存在和完善了,只有部分的接口需要进行模拟调试,这时我们用mock="mock"参数来指向到模拟数据。

    这里我使用 mock 参数控制,还有一个原因是,前端项目会根据当前是哪个环境,自动请求对应环境的接口,所有的接口均是统一控制的:

    接口的统一配置-蚊子的博客

    如上图所示,如果我们要通过环境变量控制 api 字段,最终强行修改某个接口变相请求其他环境的数据,会造成其他接口数据的混乱,最终可能的结果是页面整体会挂掉。我们在使用mock字段作为参数时,侵入的业务逻辑会维持到最小的程度,同时,也能把前后端的协作,缩小到单个接口的粒度。而且,mock 参数也只会在 local 环境生效,即使忘了去掉这个参数,也不会对线上环境造成影响。

    再有,当我们前端逻辑发生变化后,除了使用模拟数据来检验,如果线上有接口,我们也想用线上的数据检验一下。可以,当传入mock="production"的参数时,mockServer 会读取线上接口的数据并返回。

    3. mock 与 json

    有的同学会创建一个 json 文件,把接口需要的数据都放到这个 json 文件里,然后使用fs.readFile来读取。这样倒是也可以,但是当接口数据多的时候怎么办,例如有一个排行榜是要输出前 100 名、前 1000 名用户的数据,总不能复制出 1000 份用户的数据吧。

    在当前最好的方式,就是使用 mockjs 的工具来生成数据了,可以任意的随机,也可以生成任意个数的数组数据。我们这里把对参数的校验和 mock 生成的模拟数据放到一起:

    module.exports = {
      params: {
        last: {
          required: true, // 是否必须
          type: "number", // 参数的类型
          defaults: 0, // 默认值
          min: 0, // 最小值
          max: 1 // 最大值等
        }
      },
      result: {
        code: 0,
        msg: "success",
        "x-from": "mock",
        data: Mock.mock({
          "rank|100": [
            {
              "no|+1": 1,
              uin: () => Mock.Random.string(32),
              nick: () => Mock.Random.string(1, 20),
              face: () => faces[Mock.Random.integer(0, 3)],
              region: "INVALID",
              title: "初露锋芒",
              level: () => Mock.Random.integer(1, 20),
              score: () => Mock.Random.integer(1, 2000),
              winPercent: 86
            }
          ]
        })
      }
    };
    

    params 字段表示必须的参数,result 表示要返回的数据,data 中即为我们伪造的数据。

    4. 实时修改模拟数据

    我们可以在页面中直接实时修改数据,然后进行保存,自动刷新页面后,就会得到刚才想要的结果。

    实时修改模拟数据-蚊子的博客

    我们在页面中 mock 的接口都会在调试面板中展出来,默认调试面板时关闭的,开发者在点击页面右下角的灰色按钮后,可以呼起调试面板。修改里面的数据保存后,就实时看到刚才的效果。

    5. 总结

    在开发和后期维护的过程中,前端会经常遇到模拟接口数据的情况,要么是接口还没有开发完成,要么是接口不太好返回我们想要的状态。我也是在对比多种方案后,选择了适合当前项目的一种前后端协作方案。

    欢迎关注我的公众号,多多交流:
    蚊子的博客

  • 相关阅读:
    centos7 docker安装awvs
    screen命令简介-实现linux多窗口
    linux命令重命名
    iptables防止nmap扫描
    cobal strike could not start listener address already in use (bind failed)
    docker简介及安装
    「Sqlserver」数据分析师有理由爱Sqlserver之二-像使用Excel一般地使用Sqlserver
    「Sqlserver」数据分析师有理由爱Sqlserver之一-好用的插件工具推荐
    「PowerBI」分析服务多维数据结构重回关系数据库的一大绝招
    「数据分析」Sqlserver中的窗口函数的精彩应用之数据差距与数据岛(含答案)
  • 原文地址:https://www.cnblogs.com/xumengxuan/p/12376666.html
Copyright © 2020-2023  润新知