自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為了一份Mock數(shù)據(jù),開(kāi)啟了Protobuf的救贖之路

存儲(chǔ) 存儲(chǔ)軟件
Protobuf 作為一種跨平臺(tái)、語(yǔ)言無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)的方法,已廣泛應(yīng)用于網(wǎng)絡(luò)數(shù)據(jù)交換及存儲(chǔ)。

[[421682]]

一、背景

近期在做一個(gè)需求,該需求需要和后端進(jìn)行交互,為了并行開(kāi)發(fā),就跟后端產(chǎn)生了如下的對(duì)話:

前端:老鐵,可以給份mock數(shù)據(jù)嗎?

后端:mock數(shù)據(jù)太麻煩了,你自己來(lái)吧!!!

前端:我怎么知道數(shù)據(jù)長(zhǎng)啥樣,如何mock呀!(可憐)

后端:按照約定的接口mock就行,直接給我拋出了一個(gè)proto文件

前端:此時(shí)已經(jīng)一臉懵逼狀態(tài),proto是個(gè)啥?如何根據(jù)proto來(lái)mock一份數(shù)據(jù)?后端為什么要用proto,JSON不香嗎?為了彌補(bǔ)上自己欠缺的一環(huán),開(kāi)啟了Protobuf的救贖之路。

二、Protobuf是什么?

Protobuf 作為一種跨平臺(tái)、語(yǔ)言無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)的方法,已廣泛應(yīng)用于網(wǎng)絡(luò)數(shù)據(jù)交換及存儲(chǔ)。其目前已經(jīng)支持的開(kāi)發(fā)語(yǔ)言有多種(C++、Java、Python、Objective-C、C#、JavaNano、JavaScript、Ruby、Go、PHP),詳情可參考(https://github.com/52im/protobuf)。其具有如下優(yōu)缺點(diǎn):

優(yōu)點(diǎn)

(1)序列化后體積小,適合網(wǎng)絡(luò)傳輸

(2)支持跨平臺(tái)、多語(yǔ)言

(3)具有較好的升級(jí)和兼容性(具有向后兼容的特性,更新數(shù)據(jù)結(jié)構(gòu)以后,老版本依舊可以兼容)

(4)序列化和反序列化的速度較快

缺點(diǎn)

Protobuf是二進(jìn)制協(xié)議,編碼后的數(shù)據(jù)可讀性差

三、Protobuf的結(jié)構(gòu)

Protobuf用法的使用有很多,本次就通過(guò)一個(gè)例子來(lái)看看其基本使用,具體使用可以在網(wǎng)上搜索相關(guān)文檔進(jìn)行學(xué)習(xí)。

  1. syntax = "proto2" 
  2. package transferData; 
  3.  
  4. message transferMessage { 
  5.     required string name = 1; 
  6.     required int32 age = 2; 
  7.     enum SexEnum { 
  8.         Boy = 0; 
  9.         Girl = 1; 
  10.     } 
  11.     optional SexEnum SexEnum = 3; 

1.syntax = "proto2";

該行用于指定語(yǔ)法版本,目前有兩個(gè)版本proto2和proto3,兩個(gè)版本不兼容,如果不指定,默認(rèn)語(yǔ)法是proto2.

2.package transferData;

用于定義該包的包名;

3.message

message是Protobuf中最基本的數(shù)據(jù)單元,其中可以嵌套message或其它的基礎(chǔ)數(shù)據(jù)類(lèi)型的成員;

4.屬性

message中的每一行就是一個(gè)屬性,例如required string name = 1,其組成如下所示:

標(biāo)注 類(lèi)型 屬性名 屬性順序號(hào) [options]
required string name = 1 一些可選項(xiàng)

(1)標(biāo)注有三種:

required:必選屬性;

optional:可選屬性;

repeated:重復(fù)字段,類(lèi)似于動(dòng)態(tài)數(shù)組;

(2)類(lèi)型有多種,每種語(yǔ)言不同,例如:int32、int64、int、float、double、string等;

(3)屬性名:用于表征該屬性的名稱;

(4)屬性順序號(hào):protobuf為了提高數(shù)據(jù)的壓縮和可選性等功能定義的,需要按照順序進(jìn)行定義,且不允許有重復(fù);

(5)[options]:protobuf提供了一些內(nèi)置的options可供選擇想,可大大提高protobuf的擴(kuò)展性。

5.enum

定義消息類(lèi)型時(shí),可能需要某字段值是一些預(yù)設(shè)值之一,此時(shí)枚舉類(lèi)型就能夠發(fā)揮作用了。

注:protobuf還有很多用法,此處只做了簡(jiǎn)單介紹,有喜歡的同學(xué)可進(jìn)一步自己深入學(xué)習(xí)。

四、實(shí)戰(zhàn)

聊了那么多,下面就進(jìn)入實(shí)戰(zhàn)環(huán)節(jié),實(shí)戰(zhàn)將在node運(yùn)行環(huán)境下,構(gòu)建TCP連接,然后由客戶端發(fā)送經(jīng)過(guò)Protobuf序列化的內(nèi)容至服務(wù)端,然后服務(wù)端接收到信息之后進(jìn)行解析,其中proto文件的序列化和反序列化將使用protobuf.js包,其是一個(gè)純 JavaScript 實(shí)現(xiàn),支持node.js和瀏覽器。它易于使用,速度極快,并且可以使用.proto文件開(kāi)箱即用!(https://www.npmjs.com/package/protobufjs)

4.1 基本使用

本次解析.proto文件使用的是protobuf.js包,常用的方法主要有以下幾個(gè):

1.load()

用該函數(shù)加載對(duì)應(yīng)的.proto文件,加載完成之后才能夠使用里面的message以及進(jìn)行后續(xù)的操作;

2.lookupType()

在加載完.proto后,需要對(duì)使用的message進(jìn)行初始化,即完成message實(shí)例化的過(guò)程;

3.verify()

該函數(shù)用于驗(yàn)證普通對(duì)象是某滿足對(duì)應(yīng)的message結(jié)構(gòu);

4.encode()

編碼一個(gè)message實(shí)例或者可利用的普通js對(duì)象;

5.decode()

解碼buffer至一個(gè)message實(shí)例,解碼失敗會(huì)排除錯(cuò)誤;

6.create()

從一系列屬性創(chuàng)建一個(gè)新的message實(shí)例,其優(yōu)于通過(guò)fromObject創(chuàng)建,是由于其不會(huì)產(chǎn)生冗余的轉(zhuǎn)換;

7.fromObject()

將任何無(wú)效的普通js對(duì)象轉(zhuǎn)換為message實(shí)例;

8.toObject()

轉(zhuǎn)換一個(gè)message實(shí)例去一個(gè)任意的普通js對(duì)象。

該庫(kù)的使用還有一些其它方法,可以通過(guò)看其對(duì)應(yīng)文檔進(jìn)行學(xué)習(xí)。對(duì)于上述轉(zhuǎn)換關(guān)系如下圖所示(來(lái)自于官方文檔):

4.2 服務(wù)端

其是服務(wù)端,當(dāng)接收到客戶端發(fā)送的消息后,利用protobufjs庫(kù)中的decode函數(shù)進(jìn)行解析,獲取解析后的結(jié)果。

  1. const net = require('net'); 
  2. const protobuf = require('protobufjs'); 
  3.  
  4. const decodeData = data => { 
  5.     protobuf.load('./transfer.proto'
  6.     .then(root => { 
  7.         const transferMessage = root.lookupType('transferData.transferMessage'); 
  8.  
  9.         const result = transferMessage.decode(data); 
  10.         console.log(result); // transferMessage { name'狍狍', age: 1, sexEnum: 1 } 
  11.     }) 
  12.     .catch(console.log); 
  13. const server = net.createServer(socket => { 
  14.     socket.on('data', data =>{ 
  15.         decodeData(data); 
  16.     }); 
  17.  
  18.     socket.on('close', () => { 
  19.         console.log('client disconnected!!!'); 
  20.     }); 
  21. }); 
  22.  
  23. server.on('error', err => { 
  24.     throw new Error(err); 
  25. }); 
  26.  
  27. server.listen(8081, () => { 
  28.     console.log('server port is 8081'); 
  29. }); 

4.3 客戶端

其是客戶端對(duì)應(yīng)的代碼,利用protobufjs庫(kù)進(jìn)行相應(yīng)的操作,將序列化后的內(nèi)容發(fā)送至服務(wù)端。

  1. const net = require('net'); 
  2. const protobuf = require('protobufjs'); 
  3.  
  4. const data = { 
  5.     name'狍狍'
  6.     age: 1, 
  7.     sexEnum: 1 
  8. }; 
  9.  
  10. let client = new net.Socket(); 
  11. client.connect({ 
  12.     port: 8081 
  13. }); 
  14.  
  15. client.on('connect', () => { 
  16.     setMessage(data); 
  17. }); 
  18.  
  19. client.on('data', data => { 
  20.     console.log(data); 
  21.     client.end(); 
  22. }); 
  23.  
  24. function setMessage(data) { 
  25.     protobuf.load('./transfer.proto'
  26.     .then(root =>{ 
  27.         // 根據(jù)proto文件中的內(nèi)容對(duì)message進(jìn)行實(shí)例化 
  28.         const transferMessage = root.lookupType('transferData.transferMessage'); 
  29.  
  30.         // 驗(yàn)證 
  31.         const errMsg = transferMessage.verify(data); 
  32.         console.log('errMsg', errMsg); 
  33.         if (errMsg) { 
  34.             throw new Error(errMsg); 
  35.         } 
  36.  
  37.         // 轉(zhuǎn)換為message實(shí)例 
  38.         const messageFromObj = transferMessage.fromObject(data); 
  39.         console.log('messageFromObj', messageFromObj); 
  40.  
  41.         // 編碼 
  42.         const buffer = transferMessage.encode(messageFromObj).finish(); 
  43.         console.log(buffer); 
  44.  
  45.         // 發(fā)送 
  46.         client.write(buffer); 
  47.     }) 
  48.     .catch(console.log); 

 

責(zé)任編輯:武曉燕 來(lái)源: 前端點(diǎn)線面
相關(guān)推薦

2019-04-16 13:57:59

戴爾

2019-11-14 21:21:50

數(shù)據(jù)挖掘數(shù)據(jù)處理數(shù)據(jù)分析

2018-01-29 16:29:35

數(shù)據(jù)開(kāi)發(fā)從業(yè)

2020-07-15 15:38:15

人臉識(shí)別照片活化手機(jī)

2018-08-15 13:49:06

數(shù)據(jù)分析學(xué)習(xí)Python

2019-03-24 14:14:40

代碼閱讀源代碼

2020-10-11 21:52:10

數(shù)據(jù)AI指南

2023-09-29 22:41:26

Kubernetes云原生

2018-07-29 15:33:04

2018-05-03 07:06:21

開(kāi)發(fā)規(guī)范iOS

2019-12-03 10:28:53

編程語(yǔ)言PythonJava

2024-11-07 08:50:56

用戶分析分類(lèi)維度標(biāo)簽

2023-09-01 14:02:25

用戶分析攻略

2015-03-19 15:17:11

2016-11-16 13:17:29

大數(shù)據(jù)人才流動(dòng)

2019-07-17 07:07:54

MySQL數(shù)據(jù)庫(kù)索引

2024-07-10 12:11:30

數(shù)據(jù)經(jīng)營(yíng)分析業(yè)務(wù)

2018-05-22 09:07:54

數(shù)據(jù)科學(xué)語(yǔ)言職位

2017-01-05 18:39:35

數(shù)據(jù)分析大數(shù)據(jù)時(shí)代分析報(bào)告

2018-03-09 10:28:30

生態(tài)報(bào)告簽收
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)