在与后端的WebSocket通信时,前端要带一个proto文件是一个累赘的事情。首先是明显的曝光了协议实体对象,再一个浏览器客户端很容易会缓存该文件,新的协议更新可能导致客户端不能使用,另外在cdn服务器上还需要配置.proto类型客户端才能下载过去。真是遗毒不浅,自己使用的时候会注意这些,但给别人使用的时候就很不乐观了,所以这次全部将proto文件转成JavaScript对象,省去协议文件和加载的步骤。

先看代码:

  1. function createProto(name) {
  2. var args = [].slice.call(arguments, 1);
  3. var obj = new protobuf.Type(name);
  4. for (var i = 0; i < args.length; i++) {
  5. var p = args[i];
  6. var key = i + 1;
  7. obj.add(new protobuf.Field(p[0], key, p[1] || "string"));
  8. }
  9. return obj;
  10. }
  11.  
  12. function createEnum(name,list) {
  13. var obj = new protobuf.Enum(name);
  14. for (var i = 0; i < list.length; i++) {
  15. obj.add(list[i],i);
  16. }
  17. return obj;
  18. }
  19.  
  20. function loadProto(callback) {
  21. if (typeof protobuf == "undefined") return;//说明浏览器加载失败 root = new protobuf.Root().define("IMEntity");
  22. root.add(createProto("Token", ["UserID"], ["Token"], ["Device"], ["Version", "int32"], ["Appkey"]));
  23. root.add(createProto("Feedback", ["ResultCode", "int32"], ["ResultData"], ["Seq", "int32"], ["MsgID"]));
  24. root.add(createEnum("ReceiptType", ["Receive", "Read"]));
           //...
    util.triggerCallback(callback);
  25. };

proto 主要有两种类型,Type和Enum。Type对应协议中的message,相当于是类。Enum就是枚举类型

  1. var Root = protobuf.Root,
  2. Type = protobuf.Type,
  3. Field = protobuf.Field;
  4.  
  5. var AwesomeMessage = new Type("AwesomeMessage").add(new Field("awesomeField", 1, "string"));
  6.  
  7. var root = new Root().define("awesomepackage").add(AwesomeMessage);

枚举的创建不要需要Field。只需要add 字段名即可。那么接下来的问题是,手写root.add 也很烦,因为要一个一个对照属性,不断的复制粘贴,很容易出错。所以又做了个自动生成代码的页面:

  1. <textarea id="content">
  2. //登陆Token
  3. message Token{
  4. string UserID = 1; //登陆接口返回的IMUserID
  5. string Token = 2; //登陆接口返回的Token
  6. string Device = 3; //客户端设备号
  7. int32 Version = 4; //版本号,发布前与服务端约定值
  8. string Appkey = 5; //客户端Appkey
  9. }
  10.  
  11. //收到私信
  12. message ReceivePrivateMessage{
  13. string MsgID = 1; //消息id
  14. string SenderID = 2; //发送者id
  15. string ReceiverID = 3; //接收者id
  16. string Content = 4; //消息内容。客户端转换成业务相关的实体后,再做后续处理(客户端使用,服务器不做任何处理,原样下发)
  17. bool Ack = 5; //是否需要已读回执
  18. int32 SendDateTime = 6; //消息发送时间
  19. int32 ContentType = 7; //内容类型(客户端使用,服务器不做任何处理,原样下发)
  20. }
  21. //回执类型
  22. enum ReceiptType{
  23. Receive = 0; //已收回执(收到消息后立即发送给服务器的回执)
  24. Read = 1; //已读回执(用户进入消息阅读界面后发送给服务器的回执)
  25. }
  26. </textarea>
  27. <div id="result"></div>
  28. <script>
  29. function start() {
  30. $("#result").html("");
  31. $("#result").append('root = new protobuf.Root().define("IMProtoEntity")<br>');
  32.  
  33. var reg = /("([^\\\"]*(\\.)?)*")|('([^\\\']*(\\.)?)*')|(\/{2,}.*?(\r|\n))|(\/\*(\n|.)*?\*\/)/g,// 过滤注释
  34. str = $('#content').val(); // 欲处理的文本
  35. // console.log(str.match(reg));// 打印出:匹配子串
  36. var news = str.replace(reg, "");
  37. // console.log(news); // 打印出:原文本
  38. var reg1 = /[message|enum].*?{/mg;
  39. var regobj = /{[^}{]*?}/g;//新地址
  40. var names = news.match(reg1);
  41. var protos = news.match(regobj);
  42. // console.log(names, protos);
  43. var root = {};
  44. for (var i = 0; i < names.length; i++) {
  45. var rawname = names[i];
  46. var rawObj = protos[i];
  47. //if (~rawname.indexOf("message"))
  48. if (!rawObj) continue;
  49.  
  50. var name = rawname.replace("{", '').replace("message ", '').replace("enum ", '');
  51. var obj = { name: name };
  52. if (~rawname.indexOf("enum")) {
  53. obj["type"] = "enum";
  54. }
  55.  
  56. rawObj = rawObj.replace("{", '').replace("}", '');
  57. var protolist = rawObj.split(';');
  58. // console.log("protolist", protolist);
  59. var plist = [];
  60. for (var j = 0; j < protolist.length; j++) {
  61. var p = $.trim(protolist[j]);
  62. if (p) {
  63. var args = [];
  64. var list = p.split(' ');
  65. // console.log("list", list);
  66. list.forEach(function (n) {
  67. n && args.push(n);
  68. }),
  69. // console.log("args", args);
  70. plist.push(args);
  71. }
  72. }
  73. obj.list = plist;
  74. console.log(obj);
  75. toProto(obj);
  76. }
  77.  
  78. }
  79.  
  80. start();
  81.  
  82. function toProto(obj) {
  83. var root = "root";
  84. var fun = "createProto";
  85. var enumfun = "createEnum";
  86.  
  87. var str = root + '.add(';
  88. var args;
  89. if (!obj.type) {//message
  90. args = '';
  91. for (var i = 0; i < obj.list.length; i++) {
  92. var item = obj.list[i];
  93.  
  94. //老协议2.0
  95. if (item[0] == "required" || item[0] == "optional") {
  96. item.shift();
  97. }
  98. //新协议3.0
  99. if (item[0] != "string") {
  100. args += '["' + item[1] + '","' + item[0] + '"]';
  101. } else {
  102. args += '["' + item[1] + '"]';
  103. }
  104. if (i < obj.list.length - 1) args += ",";
  105. }
  106. } else {//enum
  107. args = '[';
  108. for (var i = 0; i < obj.list.length; i++) {
  109. var item = obj.list[i];
  110. args += '"' + item[0] + '"';
  111. if (i < obj.list.length - 1) args += ",";
  112. }
  113. args += ']';
  114. }
  115.  
  116. var all = str + (obj.type ? enumfun : fun) + '("' + obj.name + '",' + args + '));';
  117. // console.log(all);
  118. $("#result").append(all + "<br>");
  119. }
  120. </script>

然后页面上会得到:

红色部分复制到工程里面就可以用了。当然要带上createProto和createEnum两个方法。proto的格式要规范,毕竟start里面是以空格split的。相对于protobuf.load("xx.proto",callback)的方式要好很多。load对位置要求比较死板,一定要在根目录。而且有类型不存在就会报错,终止程序。add方法不存在找不到类型的错误。另外速度也快了很多。

自动生成proto Js语句的更多相关文章

  1. h5 录音 自动生成proto Js语句 UglifyJS-- 对你的js做了什么 【原码笔记】-- protobuf.js 与 Long.js 【微信开发】-- 发送模板消息 能编程与会编程 vue2入坑随记(二) -- 自定义动态组件 微信上传图片

    得益于前辈的分享,做了一个h5录音的demo.效果图如下: 点击开始录音会先弹出确认框: 首次确认允许后,再次录音不需要再确认,但如果用户点击禁止,则无法录音: 点击发送 将录音内容发送到对话框中.点 ...

  2. Entity Framewrok 7beta7中不同版本sql server自动生成分页sql语句的问题

    在EF中,使用linq进行分页是很方便的,假如我们有一个EMP表,结构如下: public class Emp { [Key] public Guid No { get; set; } public ...

  3. sqlite3 根据实体自动生成建表语句

      public class BuildSqlTool { public static string GetCreateTableSql(object t) { //CREATE TABLE &quo ...

  4. ADO.NET 根据实体类自动生成添加修改语句仅限Oracle使用

    话不多说直接上代码,新手上路,高手路过勿喷,请多多指教. /// <summary> /// 等于号 /// </summary> ) + Convert.ToChar() + ...

  5. Windows使用Node.js自动生成Vue.js模版环境部署步骤-----记录

    node.js官网下载并安装node 进入node文档目录下,运行cmd 输入 node -v 查看node版本 出现表示安装完成 输入 npm -v 显示npm版本信息 安装cnpm 输入 npm ...

  6. @InsertProvider 根据bean属性,自动生成插入sql语句

    以Test为例,用mybatis的@InsertProvider的注解插入数据的时候,每次都要写类似于 Mapper类 @Mapper public interface TestDao { @Inse ...

  7. ASP.NET RAZOR自动生成的js Timer

    <input type="hidden" value="@(Model.TimeLength)" id="examTimeLength" ...

  8. SpringMVC学习系列-后记 结合SpringMVC和Hibernate-validator,根据后台验证规则自动生成前台的js验证代码

    在SpringMVC学习系列(6) 之 数据验证中我们已经学习了如何结合Hibernate-validator进行后台的数据合法性验证,但是通常来说后台验证只是第二道保险,为了更好的用户体验会现在前端 ...

  9. EF-记录程序自动生成并执行的sql语句日志

    在EntityFramework的CodeFirst模式中,我们想将程序自动生成的sql语句和执行过程记录到日志中,方便以后查看和分析. 在EF的6.x版本中,在DbContext中有一个Databa ...

随机推荐

  1. ZooKeeper数据模型

    ZooKeeper有一个分层的命名空间,类似分布式文件系统.它们唯一的区别就在于在命名空间中每个节点可以有数据关联作为它们的子节点.这就像有一个文件系统允许文件也作为文件目录.节点路径通常表示为规范的 ...

  2. Javascript实现Base64解码

    工作中需要用到,在stackoverflow中找到的,实践证明可用. function decode_base64(s) { var e = {}, i, k, v = [], r = '', w = ...

  3. 有关SQL模糊查询

    执行 数据库查询时,有完整查询和模糊查询之分. 一般模糊语句如下: SELECT 字段 FROM 表 WHERE 某字段 Like 条件 其中关于条件,SQL提供了四种匹配模式: 1,%:表示任意0个 ...

  4. Windows 10环境安装VIM代码补全插件YouCompleteMe

    Windows 10环境安装VIM代码补全插件YouCompleteMe 折腾一周也没搞定Windows下安装VIM代码补全插件YouCompleteMe,今天在家折腾一天总算搞定了.关键问题是在于P ...

  5. 小程序之发起请求 wx.request(object)的坑

    这是官方的API,然后官方的实例中 wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, header: { ...

  6. php 函数形参前面加上&

    <?php function test(&$a){ $a=$a+100; } $b=1; echo $b;//输出1 test($b);//这里$b传递给函数的其实是$b的变量内容所处的 ...

  7. 【LeetCode】118. Pascal's Triangle

    题目: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,R ...

  8. SequoiaDB版本在线升级介绍说明

    1.前言 在SequoiaDB数据库发展过程中,基本保持每半年对外发行一个正式的Release版本.并且每个新发布的Release版本相对老版本而言,性能方面都有很大的提高,并且数据库也会在新版本中加 ...

  9. Visual Studio 2017离线安装包下载、安装

    1. 首先下载在线安装exe,官网地址https://www.visualstudio.com/zh-hans/downloads/ 2. 运行CMD, 执行脚本 vs_enterprise.exe ...

  10. [Paper Reading]--Exploiting Relevance Feedback in Knowledge Graph

    <Exploiting Relevance Feedback in Knowledge Graph> Publication: KDD 2015 Authors: Yu Su, Sheng ...