Google Protocol Buffer( 簡稱 Protobuf) 是 Google 公司內部的混合語言數據標準,他們用於 RPC 系統和持續數據存儲系統。前端
Protocol Buffers 是一種輕便高效的結構化數據存儲格式,能夠用於結構化數據串行化,或者說序列化。它很適合作數據存儲或 RPC 數據交換格式。可用於通信協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。爲何要講到它,由於咱們後臺的協議就是用的它。git
Mock也能夠叫mock object,模擬對象,在面向對象程序設計中,以可控的方式模擬真實對象行爲的假對象。前端比較有名的庫是Mock.js。github
爲何要mock呢?
一、先後端分離,並行開發,可以充分利用人力,避免等待。
二、能夠豐富測試用例,提早模擬不少的真實場景數據,而沒必要等到線上環境才發現問題。ajax
但Mock.js有個問題:學習和配置成本高。npm
// 配置 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這個數組。因此這裏存在着兩個問題:
一、配置成本和語法學習成本
二、後臺協議轉換爲mock語法json
不少時候,等到咱們開發完業務邏輯,已經沒有多少耐心來寫這個mock邏輯,簡單的協議還好,若是涉及到很複雜的,寫這個mock的邏輯就更加不肯意。gulp
爲了幫前端同窗偷個懶,有必要把這個過程給省了。後端
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生成的,固然咱們能夠加入一些業務的數據,這樣測試起來更加真實。
一、前端安全,模擬xss例子。
隨機生成一些xss用例,用於前端頁面的測試。
二、前端UI測試。
在實際工做中,常常會遇到文本截斷的問題。UI界面在多行文本的狀況下會不會表現正常這個問題,在這種狀況下就能夠輕易的測試出來,而不需每次叫後臺開發配合加一些假數據。
以下圖,咱們能夠針對字符串類型的數據生成一些長文本。
全部的項目都在統一框架下,每一個項目都保持統一的目錄結構,只須要自定義一些配置就能初始化項目腳手架,剩下的只須要專一於業務開發。
by addy 原創文章,歡迎轉載,但但願全文轉載,註明本文地址。http://www.iamaddy.net/2017/0...