自動產生proto Js語句

來源:互聯網
上載者:User

標籤:錯誤   entity   nts   util   pack   device   曝光   typeof   package   

在與後端的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語句

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.