Protobuf(Protocol Buffers)是一种用于序列化结构化数据的语言无关、平台无关、可扩展的机制。在JS/TS项目中,使用WebSocket与Protobuf可以实现高效的通信和数据传输。protobufjs官方仓库:https://github.com/protobufjs/protobuf.js
安装protobuf.js依赖
安装protobuf.js依赖的时候,如果你使用的cnpm源或者不是npm官方源的话,可能会报错说找不到这个依赖,需要更换为官方的npm源然后安装:https://xiaoshen.blog.csdn.net/article/details/135767569
定义proto文件
我在本地定义了一个简单的proto文件:person.proto
syntax = "proto3";
package example;message person {int32 id = 1;string name = 2;
}message person_list {repeated person Per = 1;
}
编译proto文件报错问题
编译的时候,需要使用es6模式的,不能使用commonjs,不然会报:
pnpm pbjs -t static-module -w es6 -o src/proto/person.js src/proto/person.proto
错误的编译命令:
pnpm pbjs -t static-module -w commonjs -o src/proto/person.js src/proto/person.proto
Uncaught SyntaxError: The requested module does not provide an export named
WebSocket发送Protobuf消息
将WebSocket和Protobuf结合起来使用,可以实现高效的通信和数据传输。在发送消息时,可以先将消息对象序列化成二进制数据,然后再通过WebSocket发送:
binaryType说明:WebSocket.binaryType - Web API 接口参考 | MDN
const ws = new WebSocket('ws://192.168.1.171:8989/echo');
// 必须加上,不然解析出来的数据为空
ws.binaryType = "arraybuffer"
在接收消息时,可以先将接收到的二进制数据反序列化成消息对象,然后再进行处理:
不然会报错:protobufjs_minimal.js?v=b54c0ab3:1044 Uncaught Error: illegal buffer
ws.onmessage = function (event) {console.log('Received: ' + event.data);// 必须使用Uint8Array解析数据,不然解析不出来const res = protoRoot.example.all_person.decode(new Uint8Array(event.data));console.log("解码后的内容:", res);count.value = res;};
通过结合WebSocket和Protobuf,可以实现更高效、更可靠的数据传输,提升JS/TS项目的性能和开发效率。
我本地的写的完整代码:
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import protoRoot from "@/proto/person.js"const count: any = ref()
const ws = new WebSocket('ws://192.168.1.171:8989/echo');
// 必须加上,不然解析出来的数据为空
ws.binaryType = "arraybuffer"
// 接收到消息时的处理逻辑
ws.onmessage = (event) => {count.value = event.data;
}
// 发送消息
ws.onopen = () => {ws.send('Hello, server!');
}ws.onmessage = function (event) {console.log('Received: ' + event.data);// 必须使用Uint8Array解析数据,不然解析不出来const res = protoRoot.example.person_list.decode(new Uint8Array(event.data));console.log("解码后的内容:", res);count.value = res;
};ws.onclose = function (event) {console.log('WebSocket connection closed', event);
};// 页面初始化
onMounted(() => {console.log("组件加载:", protoRoot);
})</script><template><div><div>wbsocket消息:</div><div>{{ count }}</div></div>
</template><style scoped>
.logo {height: 6em;padding: 1.5em;will-change: filter;transition: filter 300ms;
}.logo:hover {filter: drop-shadow(0 0 2em #646cffaa);
}.logo.vue:hover {filter: drop-shadow(0 0 2em #42b883aa);
}
</style>