如何编写反应原生“本地模块”(网桥),重用常用的JavaScript代码?

问题描述:

本机模块回调到JavaScript内部桥接方法,然后在内部方法中进行处理,例如将数据解析为JSON,然后引发反应本机应用程序接收的事件?如何编写反应原生“本地模块”(网桥),重用常用的JavaScript代码?

对于跨平台的桥接模块,我想避免在中复制代码 Objective C和Java。如果可能,我希望在JavaScript中编写跨平台桥接模块代码并在Android和iOS中重新使用。

我目前的解决方案:

这工作。

这将导致两次调用sendEventWithName:

  1. sendEventWithName与 “_processResponseInJavaScriptMethod”
  2. forwardEventWithName到sendEventWithName的反应本机应用程序。

问:

是否有一种方法为本地代码同步使用JS调用处理数据,然后立即将结果与sendEventWithName?

还是每个本地> JS调用都需要异步_bridge enqueueJSCall

文件:MyNativeModule.m

 
// Use forwardEventWithName to forward events 
// processed by common cross-platform JS to the react native app 
RCT_EXPORT_METHOD(forwardEventWithName:(NSString*)name 
        body:(NSString*)body) { 
    [self sendEventWithName:name body:body]; 
} 

// 1 - react native app calls sendQueryToBluetoothDevice 
// 2 - device calls commandResponse when response received 
RCT_EXPORT_METHOD(sendQueryToBluetoothDevice:(NSString*)command { 
    [_device sendCommand:command]; 
} 

// 1 - Receives XML response from external Bluetooth device 
// 2 - Sends XML to internal JS method for processing 
// 3 - Internal JS method uses forwardEventWithName 
//  to send event to react native app 
- (void) commandResponse:(NSString *) xml {  
    [self sendEventWithName:@"_processResponseInJavaScriptMethod" 
         body:@{@"xml": configuration}]; 

} 

文件:index.js(本机模块)

 
// Parse xml in common JS code for both Android and iOS native modules 
emitter.addListener("_processResponseInJavaScriptMethod", (e) => { 
    const body = parseXml(e.xml); 

    // ?? Is there a way to send event directly using JS to the react native app ?? 

    // Hack - Call native method forwardEventWithName to sendEventWithName to react native app. 
    /// 
    // This makes two _bridge enqueueJSCall's 
    // 1 - One call to sendEventWithName "_myNativeModuleInternalMethod" 
    // 2 - Second call to sendEventWithName "myNativeModuleEvent 
    MyNativeModule.forwardEventWithName(
     'myNativeModuleEventResponseReceived', 
     JSON.stringify(body)); 
    } 
}) 

不知道你的Internal bridge module Java Script method的意思,但JS代码可以传递数据本地通过方法,本地可以通过回调或承诺将数据返回给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

+0

我有本地模块工作。我只是发现自己复制了可以重用的Java和Objective C中的代码。也许我在beridge模块的index.js中添加了监听器,然后从本地代码接收回调,处理数据,然后发出事件? react-native-fetch-blob出现它可能正在做类似的事情? https://github.com/wkh237/react-native-fetch-blob –

+0

你如何构造它取决于你。你有本地的方式发送信息到JS和JS发送信息到本机。 – satya164

+0

谢谢。有没有一种方法让本地代码使用JS调用同步处理数据,然后使用sendEventWithName立即发送结果? –

我建议做对成批大桥一些阅读在本土作出反应。

原住民 - > JS

从本质上讲,你可以做的是定义上的JS侧,你会再与BatchedBridgeregisterCallableModule)注册静态方法模块 - 这就使您能够直接调用此方法从本地通过RCTBridge().enqueueJSCall,您将提供moduleDotMethod分别对应您的模块和功能;您还将传递一个唯一(或增量)标识符,您稍后将使用该标识符将响应映射到每个请求。

JS - >本地

接下来将创建一个本机模块将被称为在JS侧将数据发送回本地,传递响应数据和标识符你会然后在本地处理侧。

我已经参与了整个服务层位于JS端的项目,并且已经成功地使用了这种方法。

+0

谢谢。您可以在原始问题中添加“我的当前解决方案:”的评论吗?有没有一种方法让本地代码使用JS调用同步处理数据,然后使用sendEventWithName立即发送结果?或者是RCTBridge()。enqueueJSCall唯一的办法是? –

+0

桥上没有什么是同步的 - 最接近同步调用的是在模块上使用constantsToExport,但这些值是在运行时定义的,不能更改。你可以,如果你想使用事件调度器,但这需要你在JS端设置一个监听器。 – sooper

+0

由于没有什么是同步的,这听起来像我上面发布的“我的当前解决方案:”大概是一样好。对于未来的跨平台可重用性,我可能会考虑将C++封装在iOS的* .mm文件中,并将其封装在Android的JNI中。我一直在iOS和Android上使用Qt 5.6,这是C++环境,工作得很好。 –