JavaScriptProxy 和 runJavaScript:ASCF 里两根最重要的桥
title: JavaScriptProxy 和 runJavaScriptASCF 里两根最重要的桥date: 2026-06-26category: HarmonyOStags:HarmonyOSArkWebJavaScriptProxyrunJavaScriptJSBridgedescription: 专门解释 H5 到 ArkTS、ArkTS 到 H5 两个方向的通信JavaScriptProxy 和 runJavaScript 分别解决什么问题。JavaScriptProxy 和 runJavaScriptASCF 里两根最重要的桥看 ASCF 这类架构最先要搞清楚的不是 IPC也不是 JSVM而是这两个东西JavaScriptProxy runJavaScript它们一个负责 H5 调 ArkTS一个负责 ArkTS 回调 H5。如果这两个方向没搞清楚后面讲 Controller、Dispatcher、JSAPI、NAPI 都会乱。一、先从一个按钮开始H5 页面里有一个按钮buttononclickcallNative()调用 ArkTS/button点击之后H5 希望把请求发给 ArkTS。在 MyASCF 里它会这样写window.ascfBridge.send(JSON.stringify({requestId:req_001,action:runtime.ping,params:{from:h5},timeout:5000}))这里的window.ascfBridge不是浏览器原生对象。它是 ArkTS 通过 ArkWeb 注入给 H5 的对象。这就是JavaScriptProxy。二、JavaScriptProxyH5 调 ArkTSJavaScriptProxy解决的问题是前端页面里的 JavaScript怎么调用应用侧 ArkTS 方法ArkTS 侧注册一个对象.javaScriptProxy({object:this.bridge,name:ascfBridge,methodList:[send],controller:this.webController})H5 侧就可以调用window.ascfBridge.send(rawReq)所以它的方向是H5 / JavaScript ↓ JavaScriptProxy ↓ ArkTS这句话很重要JavaScriptProxy 是 H5 → ArkTS。它不是 ArkTS 回调 H5。三、AscfBridgeObject桥对象只是入口在 MyASCF 里ascfBridge对应 ArkTS 侧的AscfBridgeObject。它大概做这件事H5 调 window.ascfBridge.send(rawReq) ↓ AscfBridgeObject.send(rawReq) ↓ BridgeController.handle(rawReq)注意AscfBridgeObject不应该承担太多业务。它最好只做入口打印日志 接收 rawReq 交给 Controller因为真正的协议解析、分发、业务处理应该交给后面的层Controller Dispatcher Register Biz Imp这样桥对象就不会越来越臃肿。四、为什么 H5 不直接拿 send 的返回值一开始你可能会这样写constreswindow.ascfBridge.send(rawReq)这看起来很简单。但是 ASCF 这种能力调用更接近异步模型H5 发请求 ArkTS 处理 可能调用系统 API 可能调用 C 可能失败 可能超时 最后再回调 H5所以更好的做法是 Promisewindow.ascf.send(runtime.ping,params).then(res{console.log(success,res)}).catch(err{console.log(failed,err)})H5 发出去之后不是马上拿返回值而是等 ArkTS 处理完再通过回调回来。这时候就需要第二根桥runJavaScript。五、runJavaScriptArkTS 回调 H5runJavaScript解决的问题是ArkTS 怎么主动调用 H5 页面里的 JavaScript 函数H5 先定义一个全局函数window.__ascfResolvefunction(response){constitemwindow.ascf.pendingMap.get(response.requestId)if(!item){console.log(pending request not found)return}window.ascf.pendingMap.delete(response.requestId)if(response.code0){item.resolve(response)}else{item.reject(response)}}ArkTS 处理完之后this.webController.runJavaScript(window.__ascfResolve(${responseJson}))这时 H5 页面里的window.__ascfResolve被执行。所以方向是ArkTS ↓ runJavaScript ↓ H5 / JavaScript记住runJavaScript 是 ArkTS → H5。六、pendingMapPromise 怎么和回调对应起来H5 发请求时会生成一个requestIdconstrequestIdreq_Date.now()然后把 Promise 的resolve和reject保存起来window.ascf.pendingMap.set(requestId,{resolve,reject})请求发给 ArkTSwindow.ascfBridge.send(JSON.stringify(request))ArkTS 处理完之后回调 H5window.__ascfResolve({requestId:req_001,code:0,message:success,data:{}})H5 再用requestId找到对应 Promiseconstitemwindow.ascf.pendingMap.get(response.requestId)所以requestId是异步回调的钥匙。没有它多个请求同时发出时H5 就不知道哪个结果对应哪个请求。七、两根桥合起来就是 JSBridge现在可以把主链路写清楚了H5 ↓ window.ascf.send(...) ↓ window.ascfBridge.send(rawReq) ↓ JavaScriptProxy ↓ ArkTS Controller / Dispatcher / Biz / Imp ↓ runJavaScript ↓ window.__ascfResolve(response) ↓ H5 Promise resolve这就是 MyASCF 的 JSBridge 模型。注意不要把这两个方向说反JavaScriptProxyH5 → ArkTS runJavaScriptArkTS → H5八、JavaScriptProxy 和 runJavaScript 不是 IPC这两个 API 是你在应用层能看到的接口。但是如果 H5 页面运行在 WebView 渲染进程ArkTS 逻辑运行在应用主进程那么底层跨进程传消息时框架内部可能会走 IPC。所以层级关系应该是应用层能看到 JavaScriptProxy / runJavaScript 框架底层可能涉及 IPC / RenderProcess / Main Process不能简单说JavaScriptProxy IPC runJavaScript IPC更准确是JavaScriptProxy 和 runJavaScript 是上层桥接口 IPC 是底层跨进程通信机制。九、在 MyASCF 里如何验证你可以在 H5 和 ArkTS 两边都打日志。H5[H5] create request [H5] call window.ascfBridge.send [H5] window.__ascfResolve called [H5] Promise resolveArkTS[ASCF][Bridge] JavaScriptProxy send rawReq [ASCF][Controller] parsed request [ASCF][Dispatcher] dispatch action [ASCF][Register] get handler [ASCF][Controller] callbackToH5 [ASCF][WebRuntimePage] runJavaScript看到这组日志就说明两根桥跑通了。十、总结这篇只记住一句话JavaScriptProxy 解决 H5 调 ArkTS。 runJavaScript 解决 ArkTS 回调 H5。它们合起来让 H5 和 ArkTS 可以形成一次完整的异步调用。但是它们不是 IPC也不是 JSVM也不是 NAPI。下一篇再讲这些运行时概念IPC、JSVM、UIThread、libuv 到底分别是什么参考资料ArkWeb 前端页面调用应用侧函数JavaScriptProxy / registerJavaScriptProxyhttps://developer.huawei.com/consumer/cn/doc/harmonyos-guides/web-in-page-app-function-invokingArkWeb 应用侧调用前端页面函数runJavaScript / runJavaScriptExthttps://developer.huawei.com/consumer/cn/doc/harmonyos-guides/web-in-app-frontend-page-function-invokingWebviewController API 参考https://developer.huawei.com/consumer/en/doc/harmonyos-references/arkts-apis-webview-webviewcontrollerpasteboard 剪贴板 APIhttps://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-pasteboardNode-API / NAPIhttps://developer.huawei.com/consumer/en/doc/harmonyos-references-V14/napi-V14IPC / RPC 开发指导https://developer.huawei.com/consumer/en/doc/harmonyos-guides/ipc-rpc-development-guidelineJSVM API 参考https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/_j_s_v_m-V5