React Native旨在返回一条JSON消息,其中列出了要执行的突变,例如
[["createView", attrs], ["manageChildren", ...]]
。我们设计了整个系统,从不依赖于返回同步响应,并确保该列表中的所有内容都可以完全序列化为JSON并返回。
在React Native代码库*中,负责此功能的确切代码(构建JSON)在哪里?还是引用的声明可能是位于 “简化”?
我正拼命地寻找它,但似乎是在盘旋。每当我找到一条最初看起来很有前途的音轨时,似乎都无法将我引向将生成此类JSON的地方:(
* 请注意,我对Android代码库特别感兴趣;最好是RN v0.55,即撰写本文时的最新版本。
如果可能,我也对补充的“反向”代码感兴趣。我的意思是,我假设“本地”(在Android情况下为Java)代码也必须在某个时候将某些“事件”信号发送回JS,并且我假设它们也是JSON。那么,这段代码又存放在哪里?(我对接收和反序列化该JSON的JS代码感兴趣。)
(此外,如果能在基于Expo的应用程序中从JS原始格式访问那些“低级”功能(发送和接收JSON),我将不胜感激;但这在答案中是100%可选的,因为一旦我知道上述主要问题的答案,我便有足够的信心相信自己能够自己找到答案。)
注意:为全面披露,我还在HN上交叉发布了该问题,但截至撰写本文时尚未有答案。我计划在有关HN的讨论话题过时时从此处删除此说明。
基于SO提出的“相关”问题,我开始感到模糊,感觉到名为“ BatchedBridge
” 的概念/关键字可能与我要寻找的非常接近。我的直觉似乎告诉我,这可能是朝正确方向迈出的第一步。我找到了一篇博客文章,描述了如何观察通过BatchedBridge双向传播的消息,据报道会产生如下日志:
{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)}
Run Code Online (Sandbox Code Playgroud)
同一博客上的另一篇文章显示了如何通过此“桥”将事件从Java发送到JS,并在JS中监听它们。这可以回答我问题的最后部分(可选部分)的一半,该部分是关于如何从Expo中的JS订阅Java事件的。(在Java:this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("onSessionConnect", params);
在JS: DeviceEventEmitter.addListener('onSessionConnect', (event) => { console.log(event); });
)
关于RN内部的另一篇有趣的文章,源于Google搜索“ react-native BatchedBridge”作为关键字。
构建JSON的地方可能在下面的556行,尽管我不太确定:
550 void JSCExecutor::callNativeModules(Value&& value) {
...
556 auto calls = value.toJSONString();
557 m_delegate->callNativeModules(*this, folly::parseJson(calls), true);
Run Code Online (Sandbox Code Playgroud)
从下面的l.642中调用:
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));
Run Code Online (Sandbox Code Playgroud)
根据问题中链接的文章以及2015 年的一些 视频,经过一天的挖掘,我相信这确实是BatchedBridge
Java MessageQueue
/Swift 和 JS 之间调用的总线。
如果我理解正确的话,JS->Java 调用是通过MessageQueue.enqueueNativeCall完成的,定义为:
enqueueNativeCall(
moduleID: number,
methodID: number,
params: any[],
onFail: ?Function,
onSucc: ?Function,
)
Run Code Online (Sandbox Code Playgroud)
而Java->JS 调用是通过以下任一函数(在同一文件中)完成的:
callFunctionReturnFlushedQueue(module: string, method: string, args: any[])
callFunctionReturnResultAndFlushedQueue(module: string, method: string, args: any[])
invokeCallbackAndReturnFlushedQueue(cbID: number, args: any[])
Run Code Online (Sandbox Code Playgroud)
这实际上仍然没有回答关于“JSON 在哪里?”的问题,但实际上我更感兴趣的是找到总线并验证流经它的是否是 JSON。虽然我现在甚至不确定它最终是否会具体化为实际的 JSON 字符串,但我相信它至少是“意识形态上”的 JSON。IIUC上似乎不允许非 JSON 兼容的对象MessageQueue
,并且我相信“函数指针/回调”被转换为函数名称,以便可以从 Java 异步调用它们。我相信函数结果会被忽略(即所有 JS 函数都假定有void
返回类型)。
编辑:似乎callFunctionReturnResultAndFlushedQueue
返回 JS 函数的结果,因此看来它必须是非异步(阻塞)的。但是在react-native repo 中搜索m_callFunctionReturnResultAndFlushedQueueJS
和后callFunctionReturnResultAndFlushedQueue
,似乎没有一个是从任何地方调用的。在 C++ 中你永远不可能 100% 确定,但现在我会祈祷并假设它可以被安全地忽略。
归档时间: |
|
查看次数: |
150 次 |
最近记录: |