详解vue中使用protobuf踩坑记
官方解释为:
Protocolbuffersareaflexible,efficient,automatedmechanismforserializingstructureddata–thinkXML,butsmaller,faster,andsimpler.Youdefinehowyouwantyourdatatobestructuredonce,thenyoucanusespecialgeneratedsourcecodetoeasilywriteandreadyourstructureddatatoandfromavarietyofdatastreamsandusingavarietyoflanguages.Youcanevenupdateyourdatastructurewithoutbreakingdeployedprogramsthatarecompiledagainstthe"old"format.
翻译是(机翻---我英语不好)
协议缓冲区是用于序列化结构化数据的灵活,高效的自动化机制-思考XML,但更小,更快,更简单。您可以定义一次数据的结构,然后您可以使用特殊的源代码轻松地将结构化数据写入各种数据流并使用各种语言读取和读取数据。您甚至可以更新您的数据结构,而不会中断根据“旧”格式编译的已部署程序。
特点:
- 更简单
- 是3到10倍小
- 速度要快20到100倍
- 不太模糊
- 生成更易于以编程方式使用的数据访问类
代码
在github上写了个demodemo地址有需要的可以下载下来跑一下就理解了。PS:如果觉得有用请给我个小星星(笔芯~)
使用
其实最开始我尝试使用一个第三方JSprotobuf.jsprotobuf.load的时候浏览器报了个错illegaltoken'<'(/demo.proto,line1)查找了下官网issue,大意应该是proto文件多了个字符,但是我查看过proto文件并没有发现有多的'<',怎么办呢,最后放弃使用第三方。用官方提供的方法。
下载protobuf编译器
下载地址(我下载的是3.40版)github也提供了zip包,可自行下载(目前最新版本是v3.6.0)用来编译proto为JS文件方便调用
配置环境变量
由于公司用的是win10只需要将下载的文件地址添加到path即可Mac与window命令唯一的区别就是需要将protoc改成protoc.exe前提是需要添加环境变量
编写proto文件
为了确保前后一致,下面是后台写给我的一个测试proto,我司后台是java
syntax="proto2";//protobuf版本 optionjava_package="com.test.protobuf"; optionjava_outer_classname="PersonMessage"; messagePerson{ requiredint32id=1; optionalstringname=2; optionalstringemail=3; repeatedstringlist=4; extensions100to1000;//允许扩展的ID } messagePersonTree{ optionalstringid=1; optionalstringtitle=2; repeatedPersonTreechilds=3; } extendPerson{ optionalint32count=101; optionalint32likes_cnt=102; } messagePersonEx{ optionalint32id=1; extendPerson{ optionalint32px=103; optionalint32py=104; } optionalPersonp=2; }
使用vue-cli构建一个工程目录
npminstall-gvue-cli vueinitwebpackmy-project cdmy-project npminstall npmrundev
安装插件:npminstallaxioselement-uigoogle-protobuf--save
编译proto为JS
进入awesome.proto的存放路径使用如下命令protoc.exe--js_out=import_style=commonjs,binary:.awesome.proto
- 会生成一个awesome_pb.js文件
- 点击查看awesome_pb.js其实可以看到里面是生成好的方法。只需要在页面中引入JS调用即可
之后我们将这个文件引入页面,当然你也可以考虑全局引用
测试
本地测试
编写一个测试页面,创建一个测试按钮我是在测试页面importmessagesfrom'./awesome_pb.js'方法为:
methods:{ protobufferTest(){ varmessage=newmessages.Person()//调用Person对象实例化 //赋值 message.setId(23) message.setName('asd') //序列化 varbytes=message.serializeBinary() console.log(bytes)//Uint8Array(7)[8,23,18,3,97,115,100] //反序列化 varmessage2=messages.Person.deserializeBinary(bytes) console.log(message2)//proto.PersonTree{wrappers_:null,messageId_:undefined,arrayIndexOffset_:-1,array:Array(3),pivot_:1.7976931348623157e+308,…} } }
到此,本地测试完成,没什么毛病了。
前后端联调测试
前方有坑
前后传输是使用的FormData,然后悲剧的事情来了。后台解析不了。查看了下数据[8,23,18,3,97,115,100]确实是传过去了。
后来排查出原因是应该是解析成了字符串,然后数值变了。所以解析不出来。后来使用fromCharCode()方法编辑成字符串形式传输给后台。在使用charCodeAt()取值。
此方法已弃用 protobufferTest(){ varmessage=newmessages.Person()//调用Person对象实例化 //赋值 message.setId(23) message.setName('asd') //序列化 varbytes=message.serializeBinary() console.log(bytes)//Uint8Array(7)[8,23,18,3,97,115,100] vartests='' for(letindex=0;index以上方法可能存在安全隐患。向后端传值因为FormData支持两种方式传输string和blob所以将bytes存入blob中前端获取数据对axios的默认传输方式做个更改axios.defaults.responseType='arraybuffer'将以上的JS代码更改为以下内容
protobufferTest(){ varmessage=newmessages.Person() message.setId(23) message.setName('asd') varbytes=message.serializeBinary() console.log(bytes) letuploadDatas=newFormData() varblob=newBlob([bytes],{type:'application/octet-stream'}) uploadDatas.append('protobuf',blob) this.axios.post('/test',uploadDatas) .then(function(response){ console.log(response) varmessage2=messages.PersonTree.deserializeBinary(response.data) console.log(message2.getId()) }) .catch(function(error){ console.log(error) }) //console.log(bytes) }至此前后联调完成
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。