react native中使用protobufjs

原文地址:https://www.ningto.com/post/5a92c04943bef42108349a58

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);
      })
    },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Native 的路由可以使用以下几个库来实现: 1. React Navigation:React Navigation 是 React Native 最流行的路由库之一,它提供了多种路由类型和导航器,例如 Stack Navigator(堆栈导航)、Tab Navigator(标签导航)和 Drawer Navigator(抽屉导航)等。 2. React Native Navigation:React Native Navigation 是一个由 Wix 开发的路由库,它提供了原生级别的性能和体验。它支持多个平台,并且提供了多种导航器及其配置选项。 3. React Native Router Flux:React Native Router Flux 是一个基于 React Navigation 的路由库,它提供了类似于 React Router 的 API,使用起来比较方便。 下面是一个使用 React Navigation 的示例: 首先安装 React Navigation: ``` npm install @react-navigation/native ``` 然后安装 Stack Navigator: ``` npm install @react-navigation/stack ``` 在 App.js 配置 Stack Navigator: ```javascript import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import HomeScreen from './screens/HomeScreen'; import DetailScreen from './screens/DetailScreen'; const Stack = createStackNavigator(); function App() { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Detail" component={DetailScreen} /> </Stack.Navigator> </NavigationContainer> ); } export default App; ``` 在 HomeScreen.js 实现页面跳转: ```javascript import React from 'react'; import { Button } from 'react-native'; import { useNavigation } from '@react-navigation/native'; function HomeScreen() { const navigation = useNavigation(); return ( <Button title="Go to detail screen" onPress={() => { navigation.navigate('Detail'); }} /> ); } export default HomeScreen; ``` 在 DetailScreen.js 实现返回: ```javascript import React from 'react'; import { Button } from 'react-native'; import { useNavigation } from '@react-navigation/native'; function DetailScreen() { const navigation = useNavigation(); return ( <Button title="Go back" onPress={() => { navigation.goBack(); }} /> ); } export default DetailScreen; ``` 这样就完成了一个简单的路由示例,点击 HomeScreen 上的按钮可以跳转到 DetailScreen,DetailScreen 上的按钮可以返回 HomeScreen。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值