博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何根据protobuf来Mock后台返回的数据
阅读量:6290 次
发布时间:2019-06-22

本文共 4784 字,大约阅读时间需要 15 分钟。

Protobuf

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。为什么要讲到它,因为我们后台的协议就是用的它。

Mock

Mock也可以叫mock object,模拟对象,在面向对象程序设计中,以可控的方式模拟真实对象行为的假对象。前端比较有名的库是。

为什么要mock呢?

1、前后端分离,并行开发,能够充分利用人力,避免等待。
2、可以丰富测试用例,提前模拟很多的真实场景数据,而不必等到线上环境才发现问题。

但Mock.js有个问题:学习和配置成本高。

// 配置 Mock 路径require.config({    paths: {        mock: 'http://mockjs.com/dist/mock'    }})// 加载 Mockrequire(['mock'], function(Mock){    // 使用 Mock    var data = Mock.mock({        'list|1-10': [{            'id|+1': 1        }]    })    // 输出结果    document.body.innerHTML +=        '
' +        JSON.stringify(data, null, 4) +        '
'})// ==>{ "list": [ { "id": 1 }, { "id": 2 }, { "id": 3 } ]}

用它之前必须要先配置一个Ajax的请求路径,然后根据后台的协议,学习mock的语法,才能模拟出list这个数组。所以这里存在着两个问题:

1、配置成本和语法学习成本
2、后台协议转换为mock语法

很多时候,等到我们开发完业务逻辑,已经没有多少耐心来写这个mock逻辑,简单的协议还好,如果涉及到很复杂的,写这个mock的逻辑就更加不愿意。

为了帮前端同学偷个懒,有必要把这个过程给省了。

Protobuf转换为JSON

git上已经有针对Protobuf开源的js接口:。因为构建工具我们使用的是gulp,同样的也有个对应的插件:,但是没法拿来就用。

首页我们来看下这个gulp-protobufjs插件所做的事情

var gulp = require('gulp');var gulpprotobuf = require('gulp-protobufjs'); gulp.task('default', function () {  return gulp.src('file.proto')    .pipe(gulpprotobuf())    .pipe(gulp.dest('out/'));});

读取proto文件,然后生成一个文件,文件类型可以自定义。

如果产出的是.js文件,那么结果是commonjs模块文件:

module.exports = require("protobufjs").newBuilder({})['import']({    "package": "mmgameweappwap",    "syntax": "proto2",    "messages": [        {            "name": "User",            "syntax": "proto2",            "fields": [                {……

如果是.json文件:

{    "package": "mmgameweappwap",    "syntax": "proto2",    "messages": [        {            "name": "UserItem",            "syntax": "proto2",            "fields": [                {                    "rule": "required",                    "type": "string",                    "name": "user_id",                    "id": 1                },                {                    "rule": "optional",                    "type": "string",                    "name": "head_img_url",                    "id": 2                },                {                    "rule": "optional",                    "type": "string",                    "name": "nick_name",                    "id": 3                }            ]        },……

很显然,这不是我们想要的最终结果。我们想要的结果是最终的ajax返回的数据。当然有了协议的json结构,字段类型、字段名也都有了,剩下的事情就只需根据他们mock一些数据。这个json文件可以理解为对接口的一个描述文件。

pb协议的rule常见的有以下几种:

  • optional:可选

  • required:必须

  • repeated:数组

数据类型,有以下几种最基本的类型,基本都可以映射为js常用的数据类型。

图片描述

例子

在解析pb文件的时候,后台CGI接口名会被定义为message。

package mmgameweappwap;message GetDiceGameRoomRequest {    required string room_id = 1;}message GetDiceGameRoomResponse {    required int32 errcode = 1;    required string errmsg = 2;    optional OkResult data = 3;    message OkResult {        repeated UserDiceItem user_dice_list     = 1;        required uint32 room_close_remain_second = 2;        required bool room_closed                = 3;    }}

package 可以理解为模块,上文我们定义了一个mmgameweappwap模块。

  • GetDiceGameRoomRequest:请求的message

  • GetDiceGameRoomResponse:返回的message

  • GetDiceGameRoom:接口名称

一个CGI接口在pb协议中的定义一般会成对的出现。RequestResponse是所有接口标准的后缀,以区别普通的message。依赖这种规则,就可以把接口解析出来,并且也能够知道其请求、返回的message。

从上面的pb协议看,message可以被嵌套,OkResult是属于GetDiceGameRoomResponse子message。同一个pb文件下,message名可能重复,整个协议可以看成是一颗树。如果要找对应的message,必须从当前节点的子节点开始查找,否则可能找错。

处理的流程比较简单。如下图所示:

图片描述

通过分析知道接口名后,如果前端的请求都是统一的,就可以通过请求接口的代码模板生成请求代码。生成对应的API.js:

var Promise = require('js/libs/Promise');var Util    = require('js/common/util');var Mock = require('./mock');var app     = getApp();var FETCH_URL   = 'http://xxxxx/gameweappwap/';module.exports = {   getDiceGameRoom: function(data) {        return new Promise((resolve, reject) => {            if(app.mock){                resolve(Mock.getDiceGameRoom);                return;            }            app.request({                url: FETCH_URL + 'getsmobapremadeinfo',                data: {                    room_id: data.room_id, // string                 },                method: "POST",                header: {                    'content-type': 'application/json'                },                success: resolve,                fail: reject,……

exports对外的接口就是CGI的接口名:getDiceGameRoom。

request中的roomid就是从pb协议中解析出来的,后面的注释标注了其类型。这样一个ajax请求就非常的简单明了了。开发者只需要API.getDiceGameRoom调用即可。如果当前app.mock开发开启,就回直接返回mock数据。mock数据是与API.js同级的文件。
图片描述

这里的数据都是调用mock.js生成的,当然我们可以加入一些业务的数据,这样测试起来更加真实。

运用场景

1、前端安全,模拟xss例子。

图片描述

随机生成一些xss用例,用于前端页面的测试。

2、前端UI测试。

在实际工作中,经常会遇到文本截断的问题。UI界面在多行文本的情况下会不会表现正常这个问题,在这种情况下就可以轻易的测试出来,而不需每次叫后台开发配合加一些假数据。

如下图,我们可以针对字符串类型的数据生成一些长文本。

图片描述

结语

所有的项目都在统一框架下,每个项目都保持统一的目录结构,只需要自定义一些配置就能初始化项目脚手架,剩下的只需要专注于业务开发。

图片描述

by addy 原创文章,欢迎转载,但希望全文转载,注明本文地址。

你可能感兴趣的文章
使用Gradle打RPM包
查看>>
“我意识到”的意义
查看>>
淘宝天猫上新辅助工具-新品填表
查看>>
再学 GDI+[43]: 文本输出 - 获取已安装的字体列表
查看>>
nginx反向代理
查看>>
操作系统真实的虚拟内存是什么样的(一)
查看>>
hadoop、hbase、zookeeper集群搭建
查看>>
python中一切皆对象------类的基础(五)
查看>>
modprobe
查看>>
android中用ExpandableListView实现三级扩展列表
查看>>
%Error opening tftp://255.255.255.255/cisconet.cfg
查看>>
java读取excel、txt 文件内容,传到、显示到另一个页面的文本框里面。
查看>>
《从零开始学Swift》学习笔记(Day 51)——扩展构造函数
查看>>
python多线程队列安全
查看>>
[汇编语言学习笔记][第四章第一个程序的编写]
查看>>
android 打开各种文件(setDataAndType)转:
查看>>
补交:最最原始的第一次作业(当时没有选上课,所以不知道)
查看>>
Vue实例初始化的选项配置对象详解
查看>>
PLM产品技术的发展趋势 来源:e-works 作者:清软英泰 党伟升 罗先海 耿坤瑛
查看>>
vue part3.3 小案例ajax (axios) 及页面异步显示
查看>>