自动生成proto Js语句
在与后端的WebSocket通信时,前端要带一个proto文件是一个累赘的事情。首先是明显的曝光了协议实体对象,再一个浏览器客户端很容易会缓存该文件,新的协议更新可能导致客户端不能使用,另外在cdn服务器上还需要配置.proto类型客户端才能下载过去。真是遗毒不浅,自己使用的时候会注意这些,但给别人使用的时候就很不乐观了,所以这次全部将proto文件转成JavaScript对象,省去协议文件和加载的步骤。
先看代码:
function createProto(name) {
var args = [].slice.call(arguments, 1);
var obj = new protobuf.Type(name);
for (var i = 0; i < args.length; i++) {
var p = args[i];
var key = i + 1;
obj.add(new protobuf.Field(p[0], key, p[1] || "string"));
}
return obj;
} function createEnum(name,list) {
var obj = new protobuf.Enum(name);
for (var i = 0; i < list.length; i++) {
obj.add(list[i],i);
}
return obj;
} function loadProto(callback) {
if (typeof protobuf == "undefined") return;//说明浏览器加载失败 root = new protobuf.Root().define("IMEntity");
root.add(createProto("Token", ["UserID"], ["Token"], ["Device"], ["Version", "int32"], ["Appkey"]));
root.add(createProto("Feedback", ["ResultCode", "int32"], ["ResultData"], ["Seq", "int32"], ["MsgID"]));
root.add(createEnum("ReceiptType", ["Receive", "Read"]));
//...
util.triggerCallback(callback);
};
proto 主要有两种类型,Type和Enum。Type对应协议中的message,相当于是类。Enum就是枚举类型
var Root = protobuf.Root,
Type = protobuf.Type,
Field = protobuf.Field; var AwesomeMessage = new Type("AwesomeMessage").add(new Field("awesomeField", 1, "string")); var root = new Root().define("awesomepackage").add(AwesomeMessage);
枚举的创建不要需要Field。只需要add 字段名即可。那么接下来的问题是,手写root.add 也很烦,因为要一个一个对照属性,不断的复制粘贴,很容易出错。所以又做了个自动生成代码的页面:
<textarea id="content">
//登陆Token
message Token{
string UserID = 1; //登陆接口返回的IMUserID
string Token = 2; //登陆接口返回的Token
string Device = 3; //客户端设备号
int32 Version = 4; //版本号,发布前与服务端约定值
string Appkey = 5; //客户端Appkey
} //收到私信
message ReceivePrivateMessage{
string MsgID = 1; //消息id
string SenderID = 2; //发送者id
string ReceiverID = 3; //接收者id
string Content = 4; //消息内容。客户端转换成业务相关的实体后,再做后续处理(客户端使用,服务器不做任何处理,原样下发)
bool Ack = 5; //是否需要已读回执
int32 SendDateTime = 6; //消息发送时间
int32 ContentType = 7; //内容类型(客户端使用,服务器不做任何处理,原样下发)
}
//回执类型
enum ReceiptType{
Receive = 0; //已收回执(收到消息后立即发送给服务器的回执)
Read = 1; //已读回执(用户进入消息阅读界面后发送给服务器的回执)
}
</textarea>
<div id="result"></div>
<script>
function start() {
$("#result").html("");
$("#result").append('root = new protobuf.Root().define("IMProtoEntity")<br>'); var reg = /("([^\\\"]*(\\.)?)*")|('([^\\\']*(\\.)?)*')|(\/{2,}.*?(\r|\n))|(\/\*(\n|.)*?\*\/)/g,// 过滤注释
str = $('#content').val(); // 欲处理的文本
// console.log(str.match(reg));// 打印出:匹配子串
var news = str.replace(reg, "");
// console.log(news); // 打印出:原文本
var reg1 = /[message|enum].*?{/mg;
var regobj = /{[^}{]*?}/g;//新地址
var names = news.match(reg1);
var protos = news.match(regobj);
// console.log(names, protos);
var root = {};
for (var i = 0; i < names.length; i++) {
var rawname = names[i];
var rawObj = protos[i];
//if (~rawname.indexOf("message"))
if (!rawObj) continue; var name = rawname.replace("{", '').replace("message ", '').replace("enum ", '');
var obj = { name: name };
if (~rawname.indexOf("enum")) {
obj["type"] = "enum";
} rawObj = rawObj.replace("{", '').replace("}", '');
var protolist = rawObj.split(';');
// console.log("protolist", protolist);
var plist = [];
for (var j = 0; j < protolist.length; j++) {
var p = $.trim(protolist[j]);
if (p) {
var args = [];
var list = p.split(' ');
// console.log("list", list);
list.forEach(function (n) {
n && args.push(n);
}),
// console.log("args", args);
plist.push(args);
}
}
obj.list = plist;
console.log(obj);
toProto(obj);
} } start(); function toProto(obj) {
var root = "root";
var fun = "createProto";
var enumfun = "createEnum"; var str = root + '.add(';
var args;
if (!obj.type) {//message
args = '';
for (var i = 0; i < obj.list.length; i++) {
var item = obj.list[i]; //老协议2.0
if (item[0] == "required" || item[0] == "optional") {
item.shift();
}
//新协议3.0
if (item[0] != "string") {
args += '["' + item[1] + '","' + item[0] + '"]';
} else {
args += '["' + item[1] + '"]';
}
if (i < obj.list.length - 1) args += ",";
}
} else {//enum
args = '[';
for (var i = 0; i < obj.list.length; i++) {
var item = obj.list[i];
args += '"' + item[0] + '"';
if (i < obj.list.length - 1) args += ",";
}
args += ']';
} var all = str + (obj.type ? enumfun : fun) + '("' + obj.name + '",' + args + '));';
// console.log(all);
$("#result").append(all + "<br>");
}
</script>
然后页面上会得到:
红色部分复制到工程里面就可以用了。当然要带上createProto和createEnum两个方法。proto的格式要规范,毕竟start里面是以空格split的。相对于protobuf.load("xx.proto",callback)的方式要好很多。load对位置要求比较死板,一定要在根目录。而且有类型不存在就会报错,终止程序。add方法不存在找不到类型的错误。另外速度也快了很多。
自动生成proto Js语句的更多相关文章
- h5 录音 自动生成proto Js语句 UglifyJS-- 对你的js做了什么 【原码笔记】-- protobuf.js 与 Long.js 【微信开发】-- 发送模板消息 能编程与会编程 vue2入坑随记(二) -- 自定义动态组件 微信上传图片
得益于前辈的分享,做了一个h5录音的demo.效果图如下: 点击开始录音会先弹出确认框: 首次确认允许后,再次录音不需要再确认,但如果用户点击禁止,则无法录音: 点击发送 将录音内容发送到对话框中.点 ...
- Entity Framewrok 7beta7中不同版本sql server自动生成分页sql语句的问题
在EF中,使用linq进行分页是很方便的,假如我们有一个EMP表,结构如下: public class Emp { [Key] public Guid No { get; set; } public ...
- sqlite3 根据实体自动生成建表语句
public class BuildSqlTool { public static string GetCreateTableSql(object t) { //CREATE TABLE &quo ...
- ADO.NET 根据实体类自动生成添加修改语句仅限Oracle使用
话不多说直接上代码,新手上路,高手路过勿喷,请多多指教. /// <summary> /// 等于号 /// </summary> ) + Convert.ToChar() + ...
- Windows使用Node.js自动生成Vue.js模版环境部署步骤-----记录
node.js官网下载并安装node 进入node文档目录下,运行cmd 输入 node -v 查看node版本 出现表示安装完成 输入 npm -v 显示npm版本信息 安装cnpm 输入 npm ...
- @InsertProvider 根据bean属性,自动生成插入sql语句
以Test为例,用mybatis的@InsertProvider的注解插入数据的时候,每次都要写类似于 Mapper类 @Mapper public interface TestDao { @Inse ...
- ASP.NET RAZOR自动生成的js Timer
<input type="hidden" value="@(Model.TimeLength)" id="examTimeLength" ...
- SpringMVC学习系列-后记 结合SpringMVC和Hibernate-validator,根据后台验证规则自动生成前台的js验证代码
在SpringMVC学习系列(6) 之 数据验证中我们已经学习了如何结合Hibernate-validator进行后台的数据合法性验证,但是通常来说后台验证只是第二道保险,为了更好的用户体验会现在前端 ...
- EF-记录程序自动生成并执行的sql语句日志
在EntityFramework的CodeFirst模式中,我们想将程序自动生成的sql语句和执行过程记录到日志中,方便以后查看和分析. 在EF的6.x版本中,在DbContext中有一个Databa ...
随机推荐
- 微信授权登录(PHP)
微信授权登录(PHP) 微信授权 OAuth2.0授权 微信网页授权 主要是在项目中遇到网页授权登录这个需求,就对此做些总结记录. OAuth2.0授权 OAuth是一个开放协议,允许用户让第三方应用 ...
- hadoop伪分布式集群搭建与安装(ubuntu系统)
1:Vmware虚拟软件里面安装好Ubuntu操作系统之后使用ifconfig命令查看一下ip; 2:使用Xsheel软件远程链接自己的虚拟机,方便操作.输入自己ubuntu操作系统的账号密码之后就链 ...
- NodeJS 实现手机短信验证 模块阿里大于
1,NodeJS 安装阿里大于模块 切换到项目目录使用npm 安装阿里于模块 npm i node-alidayu --save 2,aliyu官网使用淘宝账户登录 登录阿里大于 https://do ...
- [0] Devexpress 控件参数集合
gridview控件/统计功能 比如对“数量”列进行统计,只要在GridControl的设计器中设置SummaryItem: SummaryItem.DisplayFormat = "{ ...
- LoadRunner11_录制Oracle数据库脚本
[oracle环境] ①oracle:无需在本地安装oracle,但是oracle的odbc驱动一定要装:(我的安装路径为 D:\oracle ).安装好后在环境变量 " Path &quo ...
- w3c编程挑战-初级脚本算法
之前偶然看到了w3c上的编程挑战题,就像拿来试试手,先做的是初级脚本算法,总体不难,如果有更好的方法,希望能一起交流! 1.翻转字符串 先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序 ...
- 关于MATLAB处理大数据坐标文件201763
目前已经找出26条特征 ,但是提交数据越来越少,给我的感觉是随机森林画的范围越来越小,输出的机器数据也越来越少,我自认为特征没太大问题 我已经将不懂之处列了出来,将于明天咨询大师级人物
- Vue 项目实战系列 (三)
我们继续前两节的开发.本节教程实现的效果如下: 效果很简单,但是实现起来却要用到Vue的很多知识,下面我们将一步一步的实现这个效果. 首先这些城市的信息都是从后台的server里面获取的,所以我们需要 ...
- java 读取excel
1. 需要下载jxl.jar包 自己研究了一下,代码如下 package file;import java.io.File;import java.io.IOException;import java ...
- Linux操作数据库基本
连接数据库MySQL中每个命令后都要以分号;结尾1: mysql -h 192.168.10.250 -u root -p2:Enter password //要求你输入密码cug313@com3:s ...