Protobuf
Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,他们用于 RPC 系统和持续数据存储系统。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。为什么要讲到它,因为我们后台的协议就是用的它。
Mock
Mock也可以叫mock object,模拟对象,在面向对象程序设计中,以可控的方式模拟真实对象行为的假对象。前端比较有名的库是Mock.js。
为什么要mock呢?
1、前后端分离,并行开发,能够充分利用人力,避免等待。
2、可以丰富测试用例,提前模拟很多的真实场景数据,而不必等到线上环境才发现问题。
但Mock.js有个问题:学习和配置成本高。
// 配置 Mock 路径
require.config({
paths: {
mock: 'http://mockjs.com/dist/mock'
}
})
// 加载 Mock
require(['mock'], function(Mock){
// 使用 Mock
var data = Mock.mock({
'list|1-10': [{
'id|+1': 1
}]
})
// 输出结果
document.body.innerHTML +=
'<pre>' +
JSON.stringify(data, null, 4) +
'</pre>'
})
// ==>
{
"list": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
]
}
用它之前必须要先配置一个Ajax的请求路径,然后根据后台的协议,学习mock的语法,才能模拟出list这个数组。所以这里存在着两个问题:
1、配置成本和语法学习成本
2、后台协议转换为mock语法
很多时候,等到我们开发完业务逻辑,已经没有多少耐心来写这个mock逻辑,简单的协议还好,如果涉及到很复杂的,写这个mock的逻辑就更加不愿意。
为了帮前端同学偷个懒,有必要把这个过程给省了。
Protobuf转换为JSON
git上已经有针对Protobuf开源的js接口:https://github.com/dcodeIO/pr...。因为构建工具我们使用的是gulp,同样的也有个对应的插件:gulp-protobufjs,但是没法拿来就用。
首页我们来看下这个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协议中的定义一般会成对的出现。Request
、Response
是所有接口标准的后缀,以区别普通的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 原创文章,欢迎转载,但希望全文转载,注明本文地址。http://www.iamaddy.net/2017/0...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。