删除文章

确定要删除这篇文章吗?

取消
确定

react native中使用protobufjs

     阅读(1326)  2018-02-25 21:55:21

javascript使用protobuf google官方已经支持了可以看这里,我只是简单的试用了下没有深究,这篇文章介绍的是dcodeIOde的protobuf.js库,web端使用还是蛮方便的,但在react native中遇到了一些坑。

载入proto文件

使用如下代码载入proto文件是不行的

var protobuf = require("protobufjs");
protobuf.load(protoFilePath)

可以用这个库自身提供的工具将proto文件转换为json文件,如:

pbjs -t json file1.proto file2.proto > bundle.json

然后,使用json的相对路径就可以load成功了

lookupTypeOrEnum

载入proto文件成功后会返回一个root对象(代表了整个proto中的package),使用root.lookupTypeOrEnum查找package中的message,如果proto中有enum枚举类型会失败,翻看了一些Issues才找到解决办法,作者的回复如下:

I see. There have been similar issues in the past and iirc these are caused by recursive dependencies in the sources (enum.js requires something that again requires enum.js) that only react native isn't able to solve for some reason. This can be solved, usually, but requires checking all the dependencies and some reordering. Have you tried using the dist files instead?

讨论的地址:https://github.com/dcodeIO/protobuf.js/issues/964

我试过使用dist遇到了一些问题没有成功,根据其中一位用户的回复,在mac上将protobuf.js降级到6.8.0版本是可以的,后来我在windows上又不能使用了,折腾一番将其降级是6.7.0又可以了。

代码片段

/**
     * 构建一个protobuf包
     */
    buildProtoPackage: function(proto_package) {
      return new Promise((resolve, reject) => {
        // 缓存load后的proto对象
        if (protobufBuilders[proto_package]) {
          return resolve(protobufBuilders[proto_package])
        }

        if (PROTO_FILE_DIR[PROTO_FILE_DIR.length - 1] !== '/') {
          PROTO_FILE_DIR += '/'
        }
        const protoFilePath = PROTO_FILE_DIR + proto_package + ".proto"
        ProtoBuf.load(protoFilePath).then((root) => {
          protobufBuilders[proto_package] = root;
          return resolve(root)
        }).catch((err) => {
          console.error('buildProtoPackage ', proto_package, err, protoFilePath)
          return reject(err)
        });
      })
    },
    /**
     * 构建一个protobuf对象
     */
    buildProtoObject: function(proto_package, proto_objectname) {
      return new Promise((resolve, reject) => {
        const packageName = proto_package
        const objectName = proto_objectname
        return this.buildProtoPackage(packageName).then((root) => {
          const obj = root.lookupTypeOrEnum(objectName)
          if (obj) {
            // console.log('buildProtoObject', proto_package, proto_objectname)
            return resolve(obj)
          }
          const errStr = 'builerProtoObject ' + objectName + ' failed'
          console.error(errStr)
          return reject(errStr)
        })
      })
    },
    request: function(cmd, proto_package, proto_request, proto_response, callback) {
      return this.buildProtoObject(proto_package, proto_request).then((obj) => {
        var payload = {}
        // 在上层填充数据
        callback.fillRequest(payload);
        // 验证填充的数据是否有效
        var errMsg = obj.verify(payload);
        if (errMsg) {
          console.error('requestOnce verify err', errMsg)
          throw Error(errMsg);
        }
        // 创建消息对象
        var message = obj.create(payload); // or use .fromObject if conversion is necessary
        // 编码二进制流
        var buffer = obj.encode(message).finish();
        // 包装成ByteBuffer
        buffer = ByteBuffer.wrap(buffer, "binary");
        this.sendmsg(cmd, buffer, proto_package, proto_response, callback, false);
      })
    },

文章评论

Keep it simple,stupid
文章数
292
总访问量
350344
今日访问
358
最近评论

xuehaoyun : 很不错,来围观一下
tujiaw : 抱歉csdn code服务关闭了,这个代码我也找不到了
于淞 : 你好,这个文章的源码能分享一下吗,songsong9181@163.com,谢谢了 上面的写错了
于淞 : 你好,这个文章的源码能分享一下吗,838106303@163.com,谢谢了 上面的链接不能用了
tujiaw : 多谢多谢
essaypinglun college-paper.org : 很好的博客,赞赞
Folly : 这个实现有点奇怪,Qt为什么没有统一的比对方法。
过多s : alert("hello, world!")
tujiaw : 还不错哦
回到顶部