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>