在 HarmonyOS 的 Stage 模型下,Web 组件的通信机制是构建混合开发(Hybrid)应用的核心。其底层依托于 Chromium 的 IPC(进程间通信) 机制,实现了 ArkTS(应用进程)与 JavaScript(渲染进程)的双向对话。
1. JS 与 ArkTS 通信的两种主流方式
A. ArkTS 调用 JS:runJavaScript
这是由原生侧主动发起的指令,类似于在浏览器控制台直接执行代码。
-
原理:将字符串形式的 JS 代码发送到渲染进程的 V8 引擎中执行。
-
示例:
TypeScript
this.controller.runJavaScript('changeColor("blue")') .then(result => { /* 接收 JS 函数的返回值 */ });
B. JS 调用 ArkTS:registerJavaScriptProxy (推荐)
这是最常用的“桥接”方式。你可以在 ArkTS 中对象注册到 Web 组件中,JS 侧就像调用本地对象一样调用它。
-
步骤:
- 在 ArkTS 定义一个类(成员函数需使用
@Concurrent或普通函数)。 - 使用
registerJavaScriptProxy注册。 - JS 侧通过
window.objName.method()调用。
- 在 ArkTS 定义一个类(成员函数需使用
2. 是否存在跨线程调用?
结论:不仅跨线程,而且跨进程。
这是理解性能瓶颈的关键:
-
进程间通信 (IPC) :ArkTS 运行在 应用主进程,而 JS 运行在 独立渲染进程。所有的通信必须经过内核的序列化和反序列化。
-
线程切换:
- 发送端:应用 UI 线程发起请求。
- 中转端:系统 I/O 线程进行 IPC 传输。
- 接收端:渲染进程的 Render Main 线程执行 JS。
3. 调用是否同步?
结论:默认是异步的,但存在特定的同步场景。
A. 异步调用(主流)
runJavaScript:它是非阻塞的,返回一个Promise。原生线程发送完指令后会继续执行后续代码,不会等待 JS 执行完毕。registerJavaScriptProxy:JS 调用原生方法时,默认也是异步分发的,避免 H5 侧因为等待原生返回而假死。
B. 同步调用(慎用)
-
runJavaScriptSync(API 10+) :HarmonyOS 提供了同步版本的接口,调用后原生线程会挂起等待 JS 返回结果。- 风险:如果 JS 侧逻辑很重,或者存在死循环,会导致应用的 UI 线程直接卡死(ANR) 。
-
JS 侧的同步感知:在 JS 侧调用原生代理方法时,虽然底层是 IPC,但 JS 引擎通常会表现为同步等待结果返回。
4. 性能优化与避坑指南
| 维度 | 表现与影响 | 优化方案 |
|---|---|---|
| 序列化开销 | 传递超大 JSON 字符串会导致明显的延迟。 | 尽量传递轻量化指令,大数据通过文件共享或 Base64 优化。 |
| 调用频率 | 每秒数百次的 Bridge 调用会撑爆 IPC 通道。 | 合并多次调用,采用“批处理”模式。 |
| 线程阻塞 | 在 Bridge 的 ArkTS 回调里做耗时计算。 | 在回调里立刻开启 TaskPool 任务,计算完再回传。 |
总结
- 方式:
runJavaScript(下行) /registerJavaScriptProxy(上行)。 - 本质:跨进程异步通信。
- 规则:除非万不得已,永远不要在 UI 线程使用同步等待接口。