如何编写重用通用 JavaScript 代码的反应原生“本机模块”(桥)?
Posted
技术标签:
【中文标题】如何编写重用通用 JavaScript 代码的反应原生“本机模块”(桥)?【英文标题】:How to write react native "native module" ( bridge ) that reuses common JavaScript code? 【发布时间】:2017-11-01 15:52:07 【问题描述】:原生模块如何回调到 javascript 内部桥接方法,然后在内部方法中进行处理,例如将数据解析为 JSON,然后引发 react native 应用接收到的事件?
对于跨平台的桥接模块,我想避免在Objective C 和Java 中重复代码。如果可能的话,我想用 JavaScript 编写跨平台的桥接模块代码,并在 android 和 ios 上重用。
我目前的解决方案:
这行得通。
这将导致对 sendEventWithName 的两次调用:
-
使用“_processResponseInJavaScriptMethod”发送EventWithName
forwardEventWithName 到 sendEventWithName 到 react native 应用程序。
问题:
有没有办法让原生代码使用 JS 调用同步处理数据,然后使用 sendEventWithName 立即发送结果?
或者是否每个原生 > JS 调用都需要异步 _bridge enqueueJSCall
?
文件:MyNativeModule.m
// 使用 forwardEventWithName 转发事件 // 普通跨平台JS处理到react native app RCT_EXPORT_METHOD(forwardEventWithName:(NSString*)name 正文:(NSString *)正文) [self sendEventWithName:name body:body]; // 1 - 响应原生应用调用 sendQueryToBluetoothDevice // 2 - 设备在收到响应时调用 commandResponse RCT_EXPORT_METHOD(sendQueryToBluetoothDevice:(NSString*)command [_device sendCommand:command]; // 1 - 从外部蓝牙设备接收 XML 响应 // 2 - 将 XML 发送到内部 JS 方法进行处理 // 3 - 内部 JS 方法使用 forwardEventWithName // 发送事件以响应本机应用程序 - (void) commandResponse:(NSString *) xml [self sendEventWithName:@"_processResponseInJavaScriptMethod" 正文:@@"xml": 配置];文件:index.js(原生模块)
// 在 Android 和 iOS 原生模块的通用 JS 代码中解析 xml 发射器.addListener("_processResponseInJavaScriptMethod", (e) => 常量体 = parseXml(e.xml); // ??有没有办法直接使用 JS 将事件发送到反应原生应用程序? // Hack - 调用原生方法 forwardEventWithName 到 sendEventWithName 来响应原生应用程序。 /// // 这使得两个 _bridge enqueueJSCall 的 // 1 - 一次调用 sendEventWithName "_myNativeModuleInternalMethod" // 2 - 第二次调用 sendEventWithName "myNativeModuleEvent MyNativeModule.forwardEventWithName( 'myNativeModuleEventResponseReceived', JSON.stringify(body)); )【问题讨论】:
【参考方案1】:我建议阅读一下 React Native 中的批处理桥。
原生 -> JS
基本上你可以做的是在 JS 端定义一个带有静态方法的模块,然后你将使用 BatchedBridge
(registerCallableModule
) 注册 - 这使你可以通过 @ 从本机端直接调用此方法987654323@,您将提供与您的模块和功能分别对应的moduleDotMethod
;您还将传递一个唯一(或增量)标识符,稍后您将使用该标识符将响应映射到每个请求。
JS -> 原生
接下来,您将创建一个本地模块,该模块将在 JS 端调用以将数据发送回本机,传递响应数据和标识符,然后您将在本机端处理。
我参与过整个服务层都在 JS 端的项目,并且成功地使用了这种方法。
【讨论】:
谢谢。您能否评论添加到原始问题的“我当前的解决方案:”?本机代码是否有一种方法可以使用 JS 调用同步处理数据,然后使用 sendEventWithName 立即发送结果?还是 RCTBridge().enqueueJSCall 是唯一的方法? 桥上没有任何东西是同步的——最接近同步调用的是在模块上使用constantsToExport
,但这些值是在运行时定义的,不能更改。如果你想使用事件调度器,你可以这样做,但这需要你在 JS 端设置一个监听器。
因为没有什么是同步的,听起来我上面发布的“我当前的解决方案:”已经差不多了。对于未来的跨平台可重用性,我可能会考虑将 C++ 包装在 iOS 的 *.mm 文件中,并考虑将 C++ 包装在 Android 的 JNI 中。我一直在为 iOS 和 Android 使用 Qt 5.6,这是一个运行良好的 C++ 环境。【参考方案2】:
不知道Internal bridge module Java Script method
是什么意思,但是JS 代码可以通过方法将数据传递给native,而native 可以通过回调或promise 将数据返回给JS。原生代码也可以向 JS 发送事件。
JS ---> Native // Method calls
Native ---> JS // Callbacks, Promises, Events
请参阅本机模块文档以获取更多详细信息: - https://facebook.github.io/react-native/docs/native-modules-ios.html - https://facebook.github.io/react-native/docs/native-modules-android.html
【讨论】:
我有本地模块工作。我只是发现自己在 Java 和 Objective C 中复制了可以重复使用的代码。也许我在 beridge 模块的 index.js 中添加了Listener,然后从本机代码接收回调,处理数据,然后发出事件? react-native-fetch-blob 似乎它可能正在做类似的事情? github.com/wkh237/react-native-fetch-blob 如何构建它取决于您自己。你有办法让 native 向 JS 发送信息和 JS 向 native 发送信息。 谢谢。有没有办法让原生代码使用 JS 调用同步处理数据,然后使用 sendEventWithName 立即发送结果? 不行,JS和Native之间不能同步传输数据。以上是关于如何编写重用通用 JavaScript 代码的反应原生“本机模块”(桥)?的主要内容,如果未能解决你的问题,请参考以下文章