詳解vue中使用protobuf踩坑記
官方解釋為:
Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages. You can even update your data structure without breaking deployed programs that are compiled against the "old" format.
翻譯是(機(jī)翻---我英語(yǔ)不好)
協(xié)議緩沖區(qū)是用于序列化結(jié)構(gòu)化數(shù)據(jù)的靈活,高效的自動(dòng)化機(jī)制 - 思考XML,但更小,更快,更簡(jiǎn)單。您可以定義一次數(shù)據(jù)的結(jié)構(gòu),然后您可以使用特殊的源代碼輕松地將結(jié)構(gòu)化數(shù)據(jù)寫(xiě)入各種數(shù)據(jù)流并使用各種語(yǔ)言讀取和讀取數(shù)據(jù)。您甚至可以更新您的數(shù)據(jù)結(jié)構(gòu),而不會(huì)中斷根據(jù)“舊”格式編譯的已部署程序。
特點(diǎn):
- 更簡(jiǎn)單
- 是3到10倍小
- 速度要快20到100倍
- 不太模糊
- 生成更易于以編程方式使用的數(shù)據(jù)訪問(wèn)類
代碼
在github上寫(xiě)了個(gè)demo demo地址 有需要的可以下載下來(lái)跑一下就理解了。PS:如果覺(jué)得有用 請(qǐng)給我個(gè)小星星 (筆芯~)
使用
其實(shí)最開(kāi)始我嘗試使用一個(gè)第三方JSprotobuf.js protobuf.load 的時(shí)候?yàn)g覽器報(bào)了個(gè)錯(cuò)illegal token '<' (/demo.proto, line 1) 查找了下官網(wǎng)issue,大意應(yīng)該是proto文件多了個(gè)字符,但是我查看過(guò)proto文件并沒(méi)有發(fā)現(xiàn)有多的'<',怎么辦呢,最后放棄使用第三方。用官方提供的方法。
下載protobuf編譯器
下載地址 (我下載的是3.40版) github也提供了zip包,可自行下載 (目前最新版本是v3.6.0) 用來(lái)編譯proto為JS文件方便調(diào)用
配置環(huán)境變量
由于公司用的是win10 只需要將下載的文件地址添加到path即可 Mac與window命令唯一的區(qū)別就是需要將protoc改成protoc.exe 前提是需要添加環(huán)境變量
編寫(xiě)proto文件
為了確保前后一致,下面是后臺(tái)寫(xiě)給我的一個(gè)測(cè)試proto,我司后臺(tái)是java
syntax = "proto2";//protobuf版本 option java_package = "com.test.protobuf"; option java_outer_classname = "PersonMessage"; message Person { required int32 id = 1; optional string name = 2; optional string email = 3; repeated string list = 4; extensions 100 to 1000;//允許擴(kuò)展的ID } message PersonTree { optional string id = 1; optional string title = 2; repeated PersonTree childs = 3; } extend Person { optional int32 count = 101; optional int32 likes_cnt= 102; } message PersonEx { optional int32 id = 1; extend Person { optional int32 px = 103; optional int32 py= 104; } optional Person p = 2; }
使用vue-cli構(gòu)建一個(gè)工程目錄
npm install -g vue-cli vue init webpack my-project cd my-project npm install npm run dev
安裝插件: npm install axios element-ui google-protobuf --save
編譯proto為JS
進(jìn)入 awesome.proto 的存放路徑 使用如下命令 protoc.exe --js_out=import_style=commonjs,binary:. awesome.proto
- 會(huì)生成一個(gè)awesome_pb.js文件
- 點(diǎn)擊查看awesome_pb.js其實(shí)可以看到里面是生成好的方法。只需要在頁(yè)面中引入JS調(diào)用即可
之后我們將這個(gè)文件引入頁(yè)面,當(dāng)然你也可以考慮全局引用
測(cè)試
本地測(cè)試
編寫(xiě)一個(gè)測(cè)試頁(yè)面,創(chuàng)建一個(gè)測(cè)試按鈕 我是在測(cè)試頁(yè)面 import messages from './awesome_pb.js' 方法為:
methods: { protobufferTest () { var message = new messages.Person() // 調(diào)用Person對(duì)象 實(shí)例化 // 賦值 message.setId(23) message.setName('asd') // 序列化 var bytes = message.serializeBinary() console.log(bytes) // Uint8Array(7) [8, 23, 18, 3, 97, 115, 100] // 反序列化 var message2 = messages.Person.deserializeBinary(bytes) console.log(message2) // proto.PersonTree {wrappers_: null, messageId_: undefined, arrayIndexOffset_: -1, array: Array(3), pivot_: 1.7976931348623157e+308, …} } }
到此,本地測(cè)試完成,沒(méi)什么毛病了。
前后端聯(lián)調(diào)測(cè)試
前方有坑
前后傳輸是使用的FormData,然后悲劇的事情來(lái)了。后臺(tái)解析不了。查看了下數(shù)據(jù) [8, 23, 18, 3, 97, 115, 100] 確實(shí)是傳過(guò)去了。
后來(lái)排查出原因是應(yīng)該是解析成了字符串,然后數(shù)值變了。所以解析不出來(lái)。 后來(lái)使用fromCharCode()方法編輯成字符串形式傳輸給后臺(tái)。在使用charCodeAt()取值。
此方法已棄用 protobufferTest () { var message = new messages.Person() // 調(diào)用Person對(duì)象 實(shí)例化 // 賦值 message.setId(23) message.setName('asd') // 序列化 var bytes = message.serializeBinary() console.log(bytes) // Uint8Array(7) [8, 23, 18, 3, 97, 115, 100] var tests = '' for (let index = 0; index < bytes.length; index++) { tests += String.fromCharCode(bytes[index]) } console.log(tests) // asd // 存入FormData let uploadDatas = new FormData() uploadDatas.append('protobuf', tests) // 使用axios傳輸給后臺(tái) this.axios.post('/test', uploadDatas) .then(function (response) { // 將傳回的字符串轉(zhuǎn)為數(shù)組 console.log(response.data.split('')) // ["↵", "", "3", "2", "", "", "a", "s", "d", "f"] let str = response.data.split('') let toChar = [] for (let index = 0; index < str.length; index++) { toChar.push(str[index].charCodeAt()) } console.log(toChar) // [10, 2, 51, 50, 18, 4, 97, 115, 100, 102] // 后臺(tái)傳回來(lái)的是PersonTree里面的值所以調(diào)用PersonTree來(lái)反序列化 var message2 = messages.PersonTree.deserializeBinary(toChar) console.log(message2) // proto.PersonTree {wrappers_: null, messageId_: undefined, arrayIndexOffset_: -1, array: Array(3), pivot_: 1.7976931348623157e+308, …} // 獲取PersonTree的id值 console.log(message2.getId()) // 32 }) .catch(function (error) { console.log(error) }) }
以上方法可能存在安全隱患。 向后端傳值 因?yàn)镕ormData支持兩種方式傳輸string和blob所以將bytes存入blob中 前端獲取數(shù)據(jù) 對(duì)axios的默認(rèn)傳輸方式做個(gè)更改 axios.defaults.responseType = 'arraybuffer' 將以上的JS代碼更改為以下內(nèi)容
protobufferTest () { var message = new messages.Person() message.setId(23) message.setName('asd') var bytes = message.serializeBinary() console.log(bytes) let uploadDatas = new FormData() var blob = new Blob([bytes], {type: 'application/octet-stream'}) uploadDatas.append('protobuf', blob) this.axios.post('/test', uploadDatas) .then(function (response) { console.log(response) var message2 = messages.PersonTree.deserializeBinary(response.data) console.log(message2.getId()) }) .catch(function (error) { console.log(error) }) // console.log(bytes) }
至此前后聯(lián)調(diào)完成
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue?router如何實(shí)現(xiàn)tab切換
這篇文章主要介紹了vue?router如何實(shí)現(xiàn)tab切換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue零基礎(chǔ)入門(mén)之模板語(yǔ)法與數(shù)據(jù)綁定及Object.defineProperty方法詳解
這篇文章主要介紹了Vue初學(xué)基礎(chǔ)中的模板語(yǔ)法、數(shù)據(jù)綁定、Object.defineProperty方法等基礎(chǔ),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09解決vue項(xiàng)目,npm run build后,報(bào)路徑錯(cuò)的問(wèn)題
這篇文章主要介紹了解決vue項(xiàng)目,npm run build后,報(bào)路徑錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08Vue項(xiàng)目保持element組件同行,設(shè)置組件不自動(dòng)換行問(wèn)題
這篇文章主要介紹了Vue項(xiàng)目保持element組件同行,設(shè)置組件不自動(dòng)換行問(wèn)題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02Vue3在css中使用v-bind綁定js/ts變量(在scss和less中使用方式)
v-bind是Vue.js中的一個(gè)核心指令,用于在Vue組件或DOM元素上綁定數(shù)據(jù)屬性,下面這篇文章主要給大家介紹了關(guān)于Vue3在css中使用v-bind綁定js/ts變量的相關(guān)資料,也可以在scss和less中使用方式,需要的朋友可以參考下2024-04-04Vue 實(shí)現(xiàn)復(fù)制功能,不需要任何結(jié)構(gòu)內(nèi)容直接復(fù)制方式
今天小編就為大家分享一篇Vue 實(shí)現(xiàn)復(fù)制功能,不需要任何結(jié)構(gòu)內(nèi)容直接復(fù)制方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11