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
 
  說明:
    *.proto        選中當前目錄的所有后綴為 .proto 的文件(也可以具體的某一個文件)。如果沒有進到 *.proto 文件所在的目錄,也可以加上路勁:../path1/*.proto 這種。但是如果proto之間有相互引用,就不要加路勁了,引用會報錯。
    --js_out      編譯目標為 js 文件
    commonjs      編譯出來的 js 文件,按照 commonjs 導入使用
    binary:./proto-js  編譯的輸出目錄,就是個相對路徑。例如一個點:binary:. 直接編譯到當前目錄。文件多的時候建一個文件夾(提前建好,不然報錯)來放比較安逸
 
我放入了一些測試文件、建了兩文件夾:
 
 
 
只要沒報錯就編譯完成了:
 
 
查看結果:

 

三、導入使用

  按照前面的 commonjs 規范,使用 require 導入:

  

  (proto源文件可能在編輯器里會飄紅報錯,不用管它...)

  嗯...使用前先:

    npm i google-protobuf

  看一下都有些啥:

  

  可以看到導入的是一個對象,里面包含了對應 .proto 文件所定義的數據結構。它們都掛載有相同的方法,可以看編譯出來的js文件:

 

  解密數據:deserializeBinary 內部調用的 deserializeBinaryFromReader 方法

  加密數據:serializeBinary 內部調用的 serializeBinaryToWriter 方法

 

  主要目標:

  1. 創建符合 protobuf 的對象,加密,以便傳輸。
  2. 解密獲取的 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 需要自己處理

 

四、小程序使用

  在小程序使用的時候遇到兩個報錯,一個是 編譯的時候  proto undefined, 一個是 socket.send 時 unknown data。

  1、proto undefined

    查資料說是小程序本身沒有支持 protobuf,可以使用其他庫來支持,亂七八糟的很多東西...。

  感覺太麻煩,就想了個辦法:我給它一個 proto。很簡單,在 protoc.exe 編譯好JS 文件里面聲明一個 proto 就好了,如果是多個編譯出的文件,可以再新建一個js文件 導出一個 proto ,再都導入引用它就好,目前沒發現有啥問題。

  2、socket.send 時 unknown data

    小程序的send方法只接受 string、arraybuffer 類型數據,proto 加密過后是 Uint8Array 嘛,轉成 arraybuffer 就號。Uint8Array.buffer 就得到 arraybuffer

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM