React Native 的 JSBridge(桥接)通信机制 是 React Native 能够实现跨平台的核心之一。理解 JSBridge 后,再学习新的 JSI、TurboModule、Fabric 就会容易很多。
一、为什么需要 JSBridge?
React Native 本质上有三个线程:
scss
┌────────────────────────────┐
│ Native 层 │
│ Android(Java/Kotlin) │
│ iOS(Objective-C/Swift) │
└─────────────▲───────────────┘
│
JSBridge
│
┌─────────────▼───────────────┐
│ JS线程 │
│ React组件 │
│ 业务代码 │
└─────────────────────────────┘
JS 代码不能直接调用 Java、Kotlin、Objective-C 或 Swift。
例如:
ini
Camera.open();
JavaScript 根本不知道:
- Camera 是什么?
- Android Camera API 在哪里?
- iOS Camera API 在哪里?
所以需要一个"翻译官"。
这个翻译官就是 JSBridge。
二、JSBridge 通信流程
例如:
ini
NativeModules.Camera.openCamera();
整个流程:
sql
React JS
↓
调用 NativeModules
↓
JSBridge
↓
Native Module
↓
Android Camera
↓
拍照
↓
返回结果
↓
JSBridge
↓
React JS
可以画成:
scss
JS
│
│ openCamera()
▼
Bridge
│
▼
Java
│
│ Camera.open()
▼
Android Camera
三、JSBridge 底层通信
实际上 JSBridge 不能直接调用 Java。
而是:
把调用信息序列化(JSON)发送过去。
例如:
JS:
dart
NativeModules.Toast.show("Hello");
Bridge 会变成:
json
{
"module":"Toast",
"method":"show",
"params":[
"Hello"
]
}
发送给 Native。
Native:
scss
收到JSON
↓
找到 Toast Module
↓
找到 show()
↓
执行
所以:
Bridge 本质上就是消息通信。
四、为什么是异步?
很多人都会问:
为什么不能这样?
ini
const result = NativeModules.Camera.open();
原因:
JS 和 Native 根本不是一个线程。
React Native:
arduino
JS Thread
Bridge
Native Thread
线程之间通信:
只能:
发送消息
等待
收到消息
不能:
同步阻塞等待
否则:
JS线程
↓
等待Native
↓
Native又等待JS
↓
死锁
因此:
React Native 从设计开始就是:
全部异步。
五、异步通信特点
例如:
JS:
csharp
NativeModules.Storage.get("token");
实际上:
JS
↓
发送消息
↓
继续执行
↓
Native收到
↓
读取SharedPreferences
↓
发送结果
↓
JS收到
因此:
JS:
vbscript
console.log("A");
NativeModules.Storage.get("token");
console.log("B");
输出:
css
A
B
(过一会)
token
不是:
css
A
token
B
六、Promise 通信
React Native 后来增加了 Promise。
Native:
Java:
typescript
@ReactMethod
public void getToken(Promise promise){
promise.resolve("abc123");
}
JS:
ini
const token = await NativeModules.Storage.getToken();
console.log(token);
实际上还是:
arduino
await
↓
Bridge发送消息
↓
Native执行
↓
resolve
↓
Bridge
↓
Promise完成
并不是同步。
只是:
javascript
Promise
帮助你
写得像同步
七、Callback 通信
最早 React Native:
ini
NativeModules.Image.pick(
success,
fail
);
Bridge:
bash
JS
↓
callback id
↓
Native
↓
执行
↓
callback id
↓
JS
所以 Native 保存:
ini
callbackId = 5
成功后:
ini
Bridge
↓
callbackId=5
↓
JS找到对应callback
↓
执行
八、为什么 JSBridge 性能不好?
因为:
每一次通信:
arduino
JS对象
↓
JSON
↓
Bridge
↓
Java对象
↓
执行
返回:
arduino
Java对象
↓
JSON
↓
Bridge
↓
JS对象
例如:
javascript
10000 次通信
↓
10000 次 JSON
↓
10000 次线程切换
这就是:
Bridge 最大瓶颈。
例如:
css
for(let i=0;i<10000;i++){
NativeModules.Test.add(i);
}
Bridge:
javascript
10000
↓
JSON
↓
Native
↓
JSON
↓
JS
非常慢。
九、Bridge 的批量通信(Batch)
React Native 为了解决频繁通信的问题,引入了批量发送机制。
不是:
JS
↓
Native
↓
JS
↓
Native
而是:
JS
↓
缓存消息
↓
一次发送
↓
Native
例如:
arduino
Message1
Message2
Message3
Message4
↓
一次Bridge发送
减少:
- 线程切换
- JSON 序列化
- IPC 开销
十、新架构为什么取消 JSBridge?
从 React Native 新架构开始,社区逐步采用 JSI(JavaScript Interface) 来替代传统 Bridge。
传统 Bridge:
arduino
JS
↓
JSON
↓
Bridge
↓
Java
JSI:
JS
↓
C++
↓
Java
特点:
- 不需要 JSON 序列化
- 减少线程切换
- 支持同步调用(在安全且适用的场景)
- 调用延迟更低
因此,新架构中的 TurboModule 和 Fabric 都建立在 JSI 之上,以解决传统 JSBridge 的性能瓶颈。
面试回答(2 分钟版本)
React Native 的 JSBridge 是 JavaScript 与 Android/iOS 原生代码之间的通信桥梁。由于 JS 引擎和 Native 运行在不同线程甚至不同运行时环境,双方不能直接调用,因此需要通过 Bridge 传递消息。
在传统架构中,JS 调用 Native 时,会将模块名、方法名和参数序列化成消息发送到 Native,Native 执行后再将结果通过 Bridge 返回给 JS。整个过程本质上是消息传递,因此天然是异步的,通常通过 Callback 或 Promise 获取结果。
JSBridge 的优点是实现了跨平台统一接口,但缺点也很明显:每次通信都需要序列化、反序列化以及线程切换,高频调用会成为性能瓶颈。React Native 为此引入了批量通信(Batch)来减少通信次数,而在新架构中进一步使用 JSI、TurboModule 和 Fabric,绕过传统 Bridge,大幅降低通信开销并提升性能。