基本概念

问题的起源:前后端分离

在前后端开发的时候,前端的数据基本都是通过api请求获取到的,但是后端可能在开发的时间上与前端不一致,这就导致前端常常需要等待后端提供接口,等待会耗去很多开发时间,所以我们经常做的方式就是自己模拟数据(假数据时代)。

比如写个定时器返回一个数据对象,或者使用一个json文件,去模拟请求。

但是这些其实都并不方便,每次都要自己去写一堆数据,如果是json格式还不能for循环,以及一些随机数据,最重要的是这些代码最终都得删除,因为耦合在业务代码中,而且我们的请求并不是真正的请求代码,最终在后端接口出来后我们还得改一遍代码。

难道就不能前端模拟的效果和真实请求一样,后端接口出来后,我通过环境变量判断一下,然后就可以直接测试了,啥代码都不用改。

为此,阿里妈妈团队开发了一个js库:mock.js

顺带吐槽一下:阿里出品,必定孤儿,19年最后一次更新至此,再无音讯,去年官方文档还能打开,现在域名都没了。

骂归骂,目前好像没有对应竞品进行替换。

使用的方式

项目中直接安装mock

最简单的就是在项目中直接安装mock.js;然后自己创建js文件,引入该库,然后写一堆配置就可以, 这个配置中你需要写一个api地址,比如我请求是https://www.a.com/api/test,那么你的配置中也得写这个地址。

mock会拦截xhr请求,如果地址能够匹配到,那么就会将自己编写的mock数据作为api结果返回,但是需要注意,由于是拦截xhr请求,所以你无法在浏览器network中看到请求记录,因为没有真实发出去请求。

先看看例子:

npm install mockjs

安装完毕我们创建一个mock的js文件,用于处理我们的mock请求

import Mock from "mockjs";

Mock.setup({
  timeout: '300-500'  //获取结果的延迟
});

const Random = Mock.Random;
Mock.mock('http://www.baidu.com/api/datadown', res => {
  let list = [];
  for (let i = 0; i < 10; i++) {
    let listobj = {
      id: Random.id(),
      title: Random.ctitle(5, 10),
    }
    list.push(listobj);
  }
  return list;
});

最终,我们在main.js中将其引入即可。

//mock
require("./mock");

mock会自动拦截axios的请求,然后模拟数据返回,axios就像正常一样使用即可。

github地址:Mock

wiki文档:wiki

由于官网死了,所以很多文档阅读并不方便,wiki文档将就看看吧!

事实上mock衍生了很多种使用方式,比如我们的mock不是一个真实请求,我们可以利用vue cli本身的node服务来搭建一个自己的mock api服务,这个就属于高阶用法了,它本质就是实现了一个server服务来创建api接口,不再是拦截xhr请求了,这种方式只是用到了mock的一些虚拟数据的方法。

高阶用法

vue cli 本身是基于webpack的,那么它的node服务也是基于webpack-dev-server,那么webpack-dev-server本身提供了一个中间件的接口,它类似于我们的axios拦截器,我们可以在拦截器里面对数据和请求做各种操作,而这个中间件接口的提供,我们可以编写自己的一些基于server的方法,比如路由,在后端中,路由其实就是我们常用的api地址。

我看了下文档,但是没有具体的实操,vue cli中提供了一个before的属性,它接受一个函数,函数接一个参数,参数为server的实例对象,可以通过该对象挂载我们的路由。

vue.config.js

import Mock from "mockjs";

//mock模拟一个数据
const data = Mock.mock({
  id: "@id()",
  username: "@cname()",
  email: "@email()"
})


module.exports = {
  devServer: {
    before(app) {
      //挂载一个路由
      app.use("/api/user", (req, res) => {
        res.json(data);
      });
    }
  }
}

看这个写法,这个server服务应该是express框架

此时我们请求接口:http://localhost:8080/api/user

就会获取到我们mock生成的data数据,此时浏览器里也有对应的network记录。

vue cli官方文档对这个before的介绍好像消失了,只是说了一句所有 webpack-dev-server 的选项都支持,我去webpack文档看了下,好像有一个新的属性叫:setupMiddlewares,通过该属性可以自由执行自定义的函数和中间件。

如果实操发现上述代码无法正确使用,可以考虑是不是api更新了,webpack文档:setupMiddlewares

缺点

说了那么多,mockjs也不是没有缺陷的,我总结下我趟过的坑。

  1. mock拦截xhr请求是破坏性的,基本上重写了xhr,这就导致我们即便没有mock数据,只要引入了mockjs就会导致xhr被重写,重写带来了不可预估的问题,其中我们的下载文件进度函数就会出现问题,我记得是。
  2. mock请求的方式无法浏览器network中查看记录
  3. 通过编写server中间件的方式可以实现api服务,也有network记录,但是耦合度非常高,明明都是相同的使用代码,多个项目无法很好的复用。

估计还有很多缺点,但是重点应该就是这几个了,所以,现在常见的mock都是自己搭建一个可视化mock服务,比如:

  • easy-mock bug有点多
  • rap2 阿里妈妈前端团队出品的开源接口管理工具RAP第二代
  • Yapi 去哪儿移动架构组开源的 之前有过bug暴雷

搭建单独的mock server

由于现在我也只是试水使用,咱们使用的Yapi搭建还挺复杂的,也懒得在搬运一套部署方法了,官方和百度都有提供详细的文档,我们就简单聊聊,东西都是可视化,我们品味下思想即可。

搭建一个单独的mock服务,服务众多项目,这也是现在业界常见的做法,解决了n多痛点:

  1. 完整的代码解耦,前端直接发起真实api请求
  2. 更加灵活,可视化选项+自定义编辑增加可用度
  3. ...

可以说mock server是现在的一大趋势,但是也并不是一记万能药,它依旧会存在一些问题,比如:

一开始前后端约定好了一些数据格式,也mock配置好,但是后面由于一些问题,后端不得不修改接口,怎么办?

前端还在使用旧的mock,或者说,后面切真实api接口时,接口的变动,没有实时的更新mock服务,这种情况肯定也会有的。

所以这个痛点在现在的一些综合工具上被想办法解决:ApiPost、ApiFox、Eolink,他们都想通过编写一个测试接口用例的同时将mock数据也一并处理了,这样当接口更新时,只需要保持测试接口的正确,mock也会同时更新到。

在Eolink中甚至将通知功能加入,当我改变一个接口时,可以发起一个通知告诉使用这个接口的人,我已经更新了。

但是很遗憾的是,这些工具并不成熟,还有很多很多的问题,而且也不是用爱发电,人家开发也要赚钱,所以有时候我们因为种种原因并不能真正的用上这些东西。

总结

综上所述,想必大家已经明白什么是mock了,它能做什么,怎么做,有哪些方式。

mock本身并不难,但是文档确实烂,如果想要熟练的使用,还得多看看文档,记那些拗口的用法,但是这并不是全部,但是它只是一种工具,略懂即可。

分类: JavaScript 标签: mock

评论

暂无评论数据

暂无评论数据

目录