【性能优化】前后端使用protobuf高效传递大量数据——前端

Protobuf简单介绍

Google Protocol Buffer(简称 Protobuf)是一种轻便高效的结构化数据存储格式,平台无关、语言无关、可扩展,可用于通讯协议和数据存储等领域。

有几个优点:

  • 1.平台无关,语言无关,可扩展;
  • 2.提供了友好的动态库,使用简单;
  • 3.解析速度快,比对应的XML快约20-100倍;
  • 4.序列化数据非常简洁、紧凑,与XML相比,其序列化之后的数据量约为1/3到1/10。

个人感受: 前后端数据传输用json还是protobuf其实对开发来说没啥区别,protobuf最后还是要解析成json才能用。个人觉得比较好的几点是:

  • 1.前后端都可以直接在项目中使用protobuf,不用再额外去定义model;
  • 2.protobuf可以直接作为前后端数据和接口的文档,大大减少了沟通成本;
  • 3.protobuf可以使数据量大大减小,在网络带宽不足的情况下效果很好。

没有使用protobuf之前,后端语言定义的接口和字段,前端是不能直接使用的,前后端沟通往往需要维护一份接口文档,如果后端字段有改动,需要去修改文档并通知前端,有时候文档更新不及时或容易遗漏,沟通成本比较大。
使用protobuf后,protobuf文件由后端统一定义,protobuf直接可以作为文档,前端只需将protobuf文件拷贝进前端项目即可。如果后端字段有改动,只需通知前端更新protobuf文件即可,因为后端是直接使用了protobuf文件,因此protobuf文件一般是不会出现遗漏或错误的。长此以往,团队合作效率提升是明显的。

思路

前端中需要使用 protobuf.js 这个库来处理proto文件。

protobuf.js 提供了几种方式来处理proto。

  • 直接解析,如protobuf.load("awesome.proto", function(err, root) {...})
  • 转化为JSON或js后使用,如protobuf.load("awesome.json", function(err, root) {...})
  • 其他

此处使用第一种方式为例:

步骤

1.拿到一份定义好的proto文件。

package awesomepackage;
syntax = "proto3";

message AwesomeMessage {
    string awesome_field = 1; // becomes awesomeField
}

2.安装protobufjs 

npm i protobufjs

 3.编码与解码

import protobuf from "protobufjs";
protobuf.load("awesome.proto", function(err, root) {
    if (err)
        throw err;

    // Obtain a message type
    var AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");

    // Exemplary payload
    var payload = { awesomeField: "AwesomeString" };

    // Verify the payload if necessary (i.e. when possibly incomplete or invalid)
    var errMsg = AwesomeMessage.verify(payload);
    if (errMsg)
        throw Error(errMsg);

    // Create a new message
    var message = AwesomeMessage.create(payload); // or use .fromObject if conversion is necessary

    // Encode a message to an Uint8Array (browser) or Buffer (node)
   // 编码
    var buffer = AwesomeMessage.encode(message).finish();
    // ... do something with buffer

    // Decode an Uint8Array (browser) or Buffer (node) to a message
   // 解码
    var message = AwesomeMessage.decode(buffer);
    // ... do something with message

    // If the application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.

    // Maybe convert the message back to a plain object
    var object = AwesomeMessage.toObject(message, {
        longs: String,
        enums: String,
        bytes: String,
        // see ConversionOptions
    });
});

效果:

 

 

 4.数据是从后端传来时axios添加响应类型:{ responseType: 'arraybuffer' }

 

axios.post(url, params, { responseType: 'arraybuffer' })

 

posted @ 2022-08-18 16:38  vickylinj  阅读(2815)  评论(0编辑  收藏  举报