手写服务器、数据Mock、前后端联调
大纲链接 §
[toc]
前端在开发中如何mock数据
- 涉及与后端交互,发送Ajax请求,从后台获取数据/向后端提交数据
- 前端按照接口文档模拟接口数据,实现前后端同步开发
- 模拟的数据和后端真实数据遵循同样的格式,内容无关紧要
- 通过模拟数据的字段,将数据展示到页面中
- 当后端完成接口后,通过联调,替换真实接口
准备
- 安装node14+或者安装node16
1. Node.js手写服务器Mock数据 ⇧
1.1 使用node.js手写server ⇧
20行代码实现server:
server.js
|  |  | 
- 命令行运行node server.js
- 实现模拟后端
- 前端发送请求至模拟后端服务器,给出对应的响应
- 调用http.createServer(()=>{}).listen(8080)创建server
- 监听8080端口
- 服务器是一个运行在机器上的软件,监听一些端口
- 当端口监听到到请求时,接收请求并发出响应
- 服务器时刻等待请求,做出响应的一个运行中的软件
server.js
|  |  | 
- 运行时一直监听8080端口
- 当浏览器输入地址http://localhost:8080时,请求到服务器上
- 请求对象req,请求相关信息
- 响应对象res:要发送响应的对象
- res.end('hello server')发送响应给浏览器
1.2 打印urlObj url字符串解析对象  ⇧ 
|  |  | 
- const url = require('url'):解析- url解析模块
- url.parse(req.url)将url字符串解析成一个对象
- 运行node server.js可以看到以下内容:
|  |  | 
- 在地址栏添加输入任意字符http://localhost:8080/aabbcc后查看可打印以下内容:
|  |  | 
- 在地址栏添加输入任意字符http://localhost:8080/123/abc.html后查看可打印以下内容:
|  |  | 
- pathname: '/123/abc.html'
- pathObj.pathname请求路径参数:指- http://localhost:8080/xxx斜杠后的内容(包括斜杠)
- 也可以包括查询参数http://localhost:8080/123/abc.html?a=1&b=2
|  |  | 
1.3 写一个简单地HTML index.html 模拟页面发起请求  ⇧ 
|  |  | 
server.js
|  |  | 
- 读取文件fs.readFileSync(__dirname + '/...')- 其中fs.readFileSync()方法表示读取
- __dirname表示当前路径- 如果在package.json中设置了"type": "module",的话,注意There is no __dirname when using ESM modules
- 添加import * as path from 'path'和const __dirname = path.resolve(path.dirname(''));
 
- 如果在
- 读取index.html:res.end(fs.readFileSync(__dirname + '/index.html'))
 
- 其中
- url.parse(req.url)在- node.js 15+后弃用,改为- let urlObj = new URL(`${req.url}`, 'http://localhost:8080/')
- 运行node server.js
- 在地址栏输入http://localhost:8080/index.html查看network面板
1.4 改为使用ES6模块 ⇧
|  |  | 
- 读取了index.html并展示到浏览器中,现在的server.js启动服务展示了index.html页面
- 模拟Ajax请求
- res.end(JSON.stringify())发出响应,传输字符串
|  |  | 
- 浏览器打开http://localhost:8080/index.html,向服务器发送请求,请求的urlObj.pathname为/,代表当前主页
- 此时urlObj.pathname为/,返回读取当前路径下的index.html文件- 获取文件的绝对路径__dirname + '/index.html'
- 读取文件内容fs.readFileSync(__dirname + '/index.html')
- 发送响应res.end(fs.readFileSync(__dirname + '/index.html')),即发送首页内容
 
- 获取文件的绝对路径
- 浏览器解析首页,执行script标签中的JS代码- JS发送Ajax请求xhr.open('GET', 'http://localhost:8080/getWeather', true)到服务器server.js
 
- JS发送Ajax请求
- 此时urlObj.pathname为/getWeather,返回数据{data: '晴天'}
小结
- 此时的服务器server.js既能够支持当前index.html的页面展示,也能支持当前需要用到的接口
1.5 功能完善 ⇧
index.html
|  |  | 
node-server/server.js
|  |  | 
- 运行node node-server/server.js
- 默认首页/,判断请求路径是否为/index.html
- 注意关闭上一个server.js,避免已使用端口address already in use :::8080
- 如果路径不为/或/index.html,就读取路径下的文件res.end(fs.readFileSync(__dirname + pathname))
- 如果读取文件失败,就走catch逻辑
- 服务器端告诉浏览器的状态码与提示文字:res.writeHead(404, 'Note Found')
- pathObj.searchParams.get('city') === 'beijing':返回一个Map类型的数据,使用Map.prototype.get方法获取值
缺点 ⇧
- 难以和后端沟通联调,统一接口文档
1.6 拓展:高级用法,手写Express.js ⇧
从实现简易Server到实现node后端框架Express.js
2 Mock.js 和 Mock 平台介绍和用法 ⇧
安装引入
Mock.js,在本地模拟数据
2.1 Mock.js用法 ⇧
预先定义好数据范例格式,随机生成数据
- 比如淘宝 Rap2 平台的mock格式
2.2 使用 Mock.js 构造随机数据示例 ⇧
构造重复的字符串
|  |  | 
- 表示生成数据对象的属性名称:合法字符串即可
- 生成规则:比如 规定范围、自增+1等
- 数据类型:真正决定生成数据类型
生成小数
|  |  | 
Boolean
|  |  | 
生成对象,包含任意可选属性
|  |  | 
生成从数组中挑选任意个数的数据组成的对象
|  |  | 
按正则生成
|  |  | 
使用 Mock.js 数据占位符  ⇧ 
Mock.mock('@...')
- 常用占位符有:
- @integer
- @boolean
- @string
- @date
- @time
- @datetime
- @now
- @image(100x100)
- @paragraph
- @cparagraph
- @name
- @cname
- @cword
- @ctitle(3, 10)
- @guid
- @email
 
|  |  | 
3. 阿里Rap2 Mock平台的使用 ⇧
- 使用不同模块来区分不同类型的功能,比如登录、注册、订单、地址管理模块等
- 新建仓库->参考示例模块->新建模块->新建接口
- 所有新建名称一般为英文,可添加中文描述
编辑接口,添加响应 ⇧
- 编写相应内容:
- 名称
- 类型
- 初始值
- 简介
 
- 保存
新建接口 getUserInfo
- 名称 getUserInfo
- 地址 /getUserInfo
- 类型 GET
- 状态码 200
- 简介 获取用户信息
编辑接口
- 添加 请求参数
- 如果类型是 GET,则请求参数放在Headers或Query Params中,Query Params更常用
- 如果类型是 POST,则请求参数放在Query Params中
- 前端向此接口发请求时,必须带上这个 请求参数,否则报错
 
- 如果类型是 
- 添加 响应内容
- 名称 name
- 必选
- 类型 String
- 生成规则
- 初始值 @cname@canme
- 简介
 
- 名称 
- 保存
@cname响应模板的随机数据格式
- 表示中文名字
导出接口 ⇧
- 可选择导出格式为markdown的接口文档,给前后端分别按文档去实现接口和mock接口,保证联调效率
后端接口检测 ⇧
rap2无法检测后端接口是否符合规定的格式
沟通确定接口文档
4. 前后端接口规范 ⇧
接口文档 ⇧
和后端沟通的过程中,必须确定好接口,根据业务分好模块,根据模块编写对应的接口规则,最终产出文档
- 前端根据接口文档去mock数据,开发页面
- 后端根据接口,开发后端功能
- 前后端联调
- 需求发生变动,更新接口文档版本,以文档为准
接口约定 ⇧
- 当前接口的路径,例如:/auth/register
- 当前接口提交数据的类型 即请求动词,(语义化接口,即RESTful风格)例如:
- GET 获取数据
- POST 提交或者创建数据
- PATCH 修改数据(部分修改)
- DELETE 删除数据
- PUT 修改数据(整体替换原有数据)
 
- 参数类型/格式,(后端接受和处理方式不同,影响发送请求是否能够被收到)例如:
- from-data,- json格式或者- application/x-www-form-urlencoded
 
- 参数字段(语义化接口可减少字段的数量),以及限制条件,例如:用户名、密码等
- 前端mock数据必须覆盖所有限制条件,包括成功和失败的所有情况
 
- 返回成功的数据格式
- 返回失败的数据格式
5. 使用curl命令行快速测试已经运行的后端接口 ⇧
当后端接口完成时,还未放入项目代码中,接口对应的UI展示和功能未完成,可以使用命令行对接口进行简单地测试
- 按接口文档约定的格式、请求动词、对应参数发送请求的时候,返回的响应是否符合规则
发送GET请求 ⇧
|  |  | 
发送POST请求 ⇧
|  |  | 
- 加上 -d修饰符,后带所需要的 请求信息,默认为POST请求
发送拥有权限的POST请求 ⇧
- 需要用户登录的信息
- 模拟用户的登录,调用接口
|  |  | 
常用curl发送POST请求修饰符
- -i展示响应头,可放命令行在末尾- 例如登录响应成功时,响应头会带着 token字段或者set-cookie字段,即用户的身份标识
- "token":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imh1bmdlcjEyIiwiaWQiOjgzLCJpYXQiOjE2Mzg5OTkyNzUsImV4cCI6MTYz OTI1ODQ3NX0.NYvilBRaPcWqXc3sspuZKk_y1DAkatcOunkRKDyd1Vo"
- 验证后续的接口时,发送请求时带上这个字段,就会让服务器识别为登录状态
- 格式为 curl -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" https://{hostname}/api/myresource
- 例如: curl -H 'Accept: application/json' -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imh1bmdlcjEyIiwiaWQiOjgzLCJpYXQiOjE2MzkwMDI4MDksImV4cCI6MTYzOTI2MjAwOX0.yyp-DzFe1XZagIjzCiBnbTDYMldT4dyU4Xy_35-BhZ4" "http://blog-server.hunger-valley.com/auth"
- google 搜索 curl with token JWT
 
- 例如登录响应成功时,响应头会带着 
- -H设置请求头信息- "Content-Type:application/json"- 在请求头里可设置 JWT Token 信息代替cookie
- curl -H 'Accept: application/json' -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imh1bmdlcjEyIiwiaWQiOjgzLCJpYXQiOjE2MzkwMDI4MDksImV4cCI6MTYzOTI2MjAwOX0.yyp-DzFe1XZagIjzCiBnbTDYMldT4dyU4Xy_35-BhZ4" "http://blog-server.hunger-valley.com/auth"
 
- -X设置请求类型 请求动词
- -b请求带上 cookie- -b "connect.sid=s%3AmeDbrn03UtTM8fqChaPQ20wmWlnKeHiu.e3uMtu7j1zQ1iNeaajCmxkYYGQ%2FyHV1ZsozMvZYWC6s"
使用 POSTMAN、Apifox 或者直接WebStorm自带 http 客户端 ⇧
- 测试接口返回不符合文档预期,可及时向后端反馈
- 实时跟踪反馈
- 自动生成接口文档
参考文章 ⇧
相关文章 ⇧
- 作者: Joel
- 文章链接:
- 版权声明
- 非自由转载-非商用-非衍生-保持署名
- 河 掘 思 知 简