在React Native代码库中,代码生成声明的"单个JSON消息"?

时间:2018-06-15 10:08:25

标签: react-native

2018 post中,Facebook工程师声称:

  

React Native旨在返回列出要执行的突变的单个JSON消息,例如[["createView", attrs], ["manageChildren", ...]]。我们将整个系统设计为永远不依赖于获取同步响应,并确保该列表中的所有内容都可以完全序列化为JSON并返回。

React Native codebase * 中的哪个是确切的代码,负责此功能(构建JSON)?或者引用的声明可能是谎言"简化"?

我拼命想找到它,但似乎是在圈子里奔跑;每当我发现一条最初似乎看起来很有前途的轨道时,它似乎永远无法将我带到一个可以生成这样的JSON的地方:(

* 请注意,我对 Android 代码库特别感兴趣;理想情况下, RN v0.55 ,这是写作时的最新版本。

如果可能,我也对补充"反向"码。我的意思是,我认为" native" (在Android的情况下为Java)代码也必须发送一些"事件"在某些时候向JS发回信号,我认为他们也是JSON。那么,这个代码在哪里生活? (我对接收和反序列化JSON的JS代码感兴趣。)

(另外,我非常感谢您了解这些"低级"功能(发送和接收JSON)是否可以从JS中以原始形式访问{{3基于应用程序;但这在答案中是100%可选的,因为我有理由相信,一旦我知道上面主要问题的答案,我就能自己找到答案。 )

注意:对于完整的披露,我也交叉发布了这个问题Expo,但截至撰写时尚无答案。当HN上的讨论主题变得过时时,我打算从此处删除此注释。

编辑No.1

基于on HN,我开始模糊地认为概念/关键字名为" BatchedBridge"可能与我正在寻找的东西非常接近。我的直觉似乎告诉我,这可能是朝着正确方向迈出的第一步。我发现了一篇描述a "Related" question suggested by SO的博客文章,据报道其结果如下所示:

{type: 1, module: "WebSocketModule", method: "addListener", args: Array(1)}
{type: 1, module: "WebSocketModule", method: "connect", args: Array(4)}
{type: 0, module: "RCTDeviceEventEmitter", method: "emit", args: Array(2)}
{type: 1, module: "Timing", method: "createTimer", args: Array(4)}

同一博客上的另一篇文章展示了如何how to observe messages flying both ways through BatchedBridge。这可以回答我的问题的最后一个可选部分的一半,关于如何在Expo中订阅来自JS的Java事件。 (在Java中:this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("onSessionConnect", params);,在JS中:DeviceEventEmitter.addListener('onSessionConnect', (event) => { console.log(event); });

另一个有趣的send events from Java to JS over this "bridge", and listen to them in JS,是通过使用Google搜索本地BatchedBridge'作为关键词。

编辑2,暂定

构建JSON的地方可能article on RN internals,但我不太确定:

550 void JSCExecutor::callNativeModules(Value&& value) {
...
556   auto calls = value.toJSONString();
557   m_delegate->callNativeModules(*this, folly::parseJson(calls), true);

称为例如line 556 below

624 void JSCExecutor::invokeCallback(
625     const double callbackId,
626     const folly::dynamic& arguments) {
...
628   auto result = [&] {
...
634       return m_invokeCallbackAndReturnFlushedQueueJS->callAsFunction(
635           {Value::makeNumber(m_context, callbackId),
636            Value::fromDynamic(m_context, std::move(arguments))});
...
642   callNativeModules(std::move(result));

1 个答案:

答案 0 :(得分:2)

根据问题中链接的文章以及2015年的some videos,经过一天的挖掘,我相信它确实是BatchedBridge,又名{{ 1}},这是在Java / Swift和JS之间调用的总线。

如果我理解正确, JS-> Java调用MessageQueue.enqueueNativeCall完成,定义为:

MessageQueue

虽然 Java-> JS调用是通过以下任何一个函数完成的(在同一个文件中):

  enqueueNativeCall(
    moduleID: number,
    methodID: number,
    params: any[],
    onFail: ?Function,
    onSucc: ?Function,
  )

这实际上仍然没有回答关于“JSON在哪里?”的问题,但实际上我更感兴趣的是找到总线并验证是否它正在流经它的JSON。虽然我现在甚至不确定它是否最终成为实际的JSON字符串,但我相信它至少是“意识形态上的”JSON。在callFunctionReturnFlushedQueue(module: string, method: string, args: any[]) callFunctionReturnResultAndFlushedQueue(module: string, method: string, args: any[]) invokeCallbackAndReturnFlushedQueue(cbID: number, args: any[]) IIUC上似乎不允许使用非JSON兼容的对象,我相信“函数指针/回调”会转换为函数名称,因此可以从Java异步调用它们。我相信函数结果被忽略(即假设所有JS函数都有MessageQueue返回类型)。

编辑: void似乎返回了JS函数的结果,因此它似乎必须是非异步(阻塞)。但在搜索callFunctionReturnResultAndFlushedQueuem_callFunctionReturnResultAndFlushedQueueJS的反应原生仓库后,似乎没有任何一个在任何地方被调用。在C ++中你永远不可能100%肯定,但是现在我会交叉指责并认为可以安全地忽略它。