笔记:微信小游戏使用protobuf/protobuf的两种加载方式

记录开发过程中的小问题,请多指教
由于是直接从微信文制过来,文章样式格式有点乱·····
完整样式请阅读微信原文
更多笔记和源码请访问公众号

​protobuf:
protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。

技术摘要

静态加载(适用于微信小游戏)

动态加载(不适用于微信小游戏)

准备工作

下载protobufjs,最新版本为v6.8.8:
https://www.npmjs.com/package/protobufjs

根据需要提取相关js,放入目标目录

创建proto文件:

syntax = “proto3”;
package tutorial;

message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
}

message AddressBook {
repeated Person people = 1;
}

​静态加载

1编译proto为js

下载protoc编译器,将proto编译为js:
https://repo1.maven.org/maven2/com/google/protobuf/protoc/

这里我将下载好的protoc和proto文件放在同一目录内

在目录内打开控制台,根据需要输入command

生成单个proto的js:

pbjs -t static-module -w commonjs -o addressbook_pb.js addressbook.proto

目录内所有proto生成一个js:
pbjs -t static-module -w commonjs -o proto.js *.proto

生成后目录内的文件如下:

将生成的js文件放入目标目录內

修改刚刚生成的js文件头部,引入正确的protobuf.js

ps:关于引入方式,历史笔记中有详细介绍

// var $protobuf = require(“protobufjs/minimal”);
var $protobuf = require("./protobuf.js");

2编码和解码

引入proto:
import { tutorial } from “…/protobuf/addressbook_pb.js”

encode/decode:

let person = tutorial.Person.create({ name: “Tom”, id: 18, email: “tom@email” });
let buffer = tutorial.Person.encode(person).finish();
let message = tutorial.Person.decode(buffer);
console.log(buffer);
console.log(message);

let people = [{ name: “Tom”, id: 18, email: “tom@email” },
{ name: “Lili”, id: 20, email: “lili@email” }
];
let payload = tutorial.AddressBook.create({ people: people });
buffer = tutorial.AddressBook.encode(payload).finish();
message = tutorial.AddressBook.decode(buffer);
console.log(buffer);
console.log(message);

打印结果:

动态加载

直接load所需的proto文件就可以使用,更加灵活
相比静态加载,也可以有效减少js文件
但其内部使用了Function,而微信小游戏中禁止动态生成代码的行为,所以在不能使用动态加载

这里需要对protobuf.js进行改造
在fetch函数中增加动态加载资源(cc.loader.loadRes),获取proto内容

proto文件放到resources目录下

引入protobuf:
import * as protobuf from “./protobuf.js”;

加载proto文件:

load(fileName) {
return new Promise((resolve, reject) => {
protobuf.load(fileName, (err, root) => {
if (err) {
reject(err);
} else {
this._root = root;
resolve();
}
});
});
}

decode:

//packageMessage: package.message
decode(packageMessage: string, buffer) {
//lookup等价于lookupTypeOrEnum
//不同的是lookup找不到返回null,lookupTypeOrEnum找不到则是抛出异常
let message = null;

let data = this._root.lookup(packageMessage);
if (data != null) {
message = data.decode(buffer);
}

return message;
}

encode:

//packageMessage: package.message
encode(packageMessage: string, obj) {
let buffer = null;

let data = this._root.lookup(packageMessage);
if (data != null) {
let message = data.create(obj);
buffer = data.encode(message).finish();
}

return buffer;
}

使用:
let proto = LoadProto.getInstance();
proto.load(“proto/addressbook”)
.then(() => {
let person = { name: “Tom”, id: 18, email: “tom@email” };
let buffer = proto.encode(“tutorial.Person”, person);
let message = proto.decode(“tutorial.Person”, buffer);
console.log(buffer);
console.log(message);

let people = [{ name: "Tom", id: 18, email: "tom@email" },
  { name: "Lili", id: 20, email: "lili@email" }
];
let payload = { people: people };
buffer = proto.encode("tutorial.AddressBook", payload);
message = proto.decode("tutorial.AddressBook", buffer);
console.log(buffer);
console.log(message);

});

打印结果:

1赞

更好的阅读体验:
https://mp.weixin.qq.com/s/OIkcsJQfLSXnZoUfXZ61AQ

找不到命令pbjs是因为什么呀老师 我用的第一种静态的方法

https://www.cnblogs.com/muzzik/p/17060955.html

成功了感谢大佬