web前端 js環境 使用 protobuf google-protobuf
google-protobuf 官網地址https://developers.google.com/protocol-buffers/
網上有些封裝過後支援前端使用的 google-protobu f庫,比如protobufjs ,不過看了下不太喜歡...
感覺就還是使用google-protobuf 官網提供的比較舒心!
一、安裝protoc編譯器
官網下載地址:https://github.com/protocolbuffers/protobuf/releases
開啟網址:
下拉:
本來打算直接下載protobuf-all-3.14.0.zip 壓縮包,畢竟誰在乎佔用那幾M大小嘛...安裝了,能編譯成對應的JS、GO等等就比較好...
結果不行:
編譯是用的一個 protoc.exe 可執行檔案,這裡面就沒有。
要下載對應系統的壓縮包!
下載protoc-3.14.0-win64.zip (對應自己的系統),解壓,進入 bin 資料夾就發現 protoc.exe 檔案了:
現在就可以用這個protoc.exe 編譯檔案了。可以每次進到這個目錄執行,也可以加入環境變數,就可以在自己的專案編輯器裡面直接使用。
二、根據 *.proto 檔案,編譯為對應語言的檔案
直接在目錄位置輸入 cmd 然後回車 開啟在當前目錄的命令列工具
輸入編譯命令:
protoc*.proto--js_out=import_style=commonjs,binary:../pb三、匯入使用
按照前面的 commonjs 規範,使用 require 匯入:
(proto原始檔可能在編輯器裡會飄紅報錯,不用管它...)
嗯...使用前先:
npm igoogle-protobuf
看一下都有些啥:
可以看到匯入的是一個物件,裡面包含了對應 .proto 檔案所定義的資料結構。它們都掛載有相同的方法,可以看編譯出來的js檔案:
解密資料:deserializeBinary 內部呼叫的deserializeBinaryFromReader 方法
加密資料:serializeBinary 內部呼叫的serializeBinaryToWriter 方法
主要目標:
- 建立符合 protobuf 的物件,加密,以便傳輸。
- 解密獲取的protobuf 壓縮的資料,解析為 js 物件。
具體例子:
let proto = require("../pb/conn.int_pb"); const protoObj = new proto.Image()//以 new 的方式建立 console.log(protoObj)//輸出一個物件 可以看到有一個array屬性 array: [] 其實所有的屬性值就會放裡面,沒設定時是空的 //設定對應的屬性 (自己確定好屬性值的型別) protoObj.setId('123') protoObj.setWidth(88) protoObj.setUrl('123') console.log(protoObj)//可以看到設定的值 array: [ '123', 88, 88, '123' ] const protoData = protoObj.serializeBinary()//加密 console.log(protoData)//一串Uint8Array陣列值 protobuf 加密過後都是 Uint8Array 型別的資料 const newProtoObj = proto.Image.deserializeBinary(protoData)//解密 必須以對應的資料結構呼叫方法 傳入資料 console.log(newProtoObj)//和 protoObj 資料就一樣了 console.log(newProtoObj.getId())// "123" console.log(newProtoObj.getWidth())// 88 console.log(newProtoObj.getHeight())// 0 存在的屬性 但是前面沒有賦值 console.log(newProtoObj.getUrl())// "123" console.log(newProtoObj.getThumbnailUrl())// "" 存在 但是前面沒有賦值 是個空串 // console.log(newProtoObj.getTThumbnailUrl())//不存在的屬性 報錯 TypeError: newProtoObj.getTThumbnailUrl is not a function //不存在的屬性都會報錯,存在的屬性都會有對應的預設值 //可以看出來,預設是每個屬性都有對應的 get、set方法
// 設定屬性好像沒有簡便方法,我看了看編譯出來的js檔案,反正我沒瞅見,但是獲取有一個,就是 toObject const jsObj = newProtoObj.toObject()//其實就是呼叫了一遍get方法 //會輸出包含所有屬性的一個js物件,沒有設定的值就是預設值 console.log(jsObj)//直接輸出jsObj { id: '123', width: 88, height: 0, url: '123', thumbnailUrl: '' } // 自己寫一個設定的方法 function formatSetStruct(structType, structData) {//傳入需要的結構型別和對應資料 const newStruct = new proto[structType](); for (let key in structData) {//遍歷設定一遍就好 if (Object.hasOwnProperty.call(structData, key)) { let setKey = "set" + key; newStruct[setKey](structData[key]); } } return newStruct.serializeBinary();//直接返回加密的資料 } const testFormat = formatSetStruct('Image', { Id : '123123adas', //string Width : 123, //int32 Height : 67, //int32 Url : '地址', //string ThumbnailUrl : '縮圖地址', //string }) const testJsObj = proto.Image.deserializeBinary(testFormat).toObject() console.log(testJsObj) // { // id: '123123adas', // width: 123, // height: 67, // url: '地址', // thumbnailUrl: '縮圖地址' // } //但是有些特殊情況, proto裡面設定的 userIds repeated string 到了js這邊 就是 UserIdsList 了 // userIds 屬性對映為了 UserIdsList 需要自己處理
OK!