當前位置:
首頁 > 知識 > 自動生成proto Js語句

自動生成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,}.*?(
|
))|(/*(
|.)*?*/)/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>

然後頁面上會得到:

自動生成proto Js語句

紅色部分複製到工程裡面就可以用了。當然要帶上createProto和createEnum兩個方法。proto的格式要規範,畢竟start裡面是以空格split的。相對於protobuf.load("xx.proto",callback)的方式要好很多。load對位置要求比較死板,一定要在根目錄。而且有類型不存在就會報錯,終止程序。add方法不存在找不到類型的錯誤。另外速度也快了很多。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

原型原型鏈學習記錄
iOS用域名或主機名獲取IP地址
默默前行的livego——基於go語言的rtmp直播伺服器

TAG:科技優家 |

您可能感興趣

rapid-generator自動生成代碼步驟
Mybatis+velocity自動生成代碼
自定義Android註解Part2:代碼自動生成
TensorFlow官方力推、GitHub爆款項目:用Attention模型自動生成圖像字幕
Angr AEG:堆溢出之Exploit自動生成
SpringMVC,Spring,Hibernate框架自動生成器
facebook:用音樂生成3D動畫
Gradle Kotlin DSL的accessors 生成問題
Python自動生成表情包
mysql8+mybatis-plus3.1自動生成lombok和swagger和增刪改查介面
「python」生成器的高級應用send、close和throw方法
使用gradle生成Spring Boot應用的Docker Image
NetCore2.1 WebAPI 根據swagger.json自動生成客戶端代碼
Regenerate Thumbnails讓WordPress重新生成特色圖像更簡單
Photo-Sketching 從圖片到塗鴉:高品質塗鴉的自動生成
python機器學習庫sklearn——生成樣本數據
LeaFlet學習之結合turf.js生成簡單的等值線demo
WordPress怎麼生成sitemap.xml?插件XML Sitemap & Google News
谷歌大腦Wasserstein自編碼器:新一代生成模型演算法
靜態站點生成器:makesite.py