H5 如何调用 ArkTSJavaScriptProxy、requestId 和 Promise 回调项目地址https://github.com/lichenyang5/MiniAppRuntime-Harmony本文是 MiniAppRuntime-Harmony 系列的第三篇重点讲 H5 到 ArkTS 的最小通信边界。1. JSBridge 的本质是什么JSBridge 听起来很抽象。但拆开看它其实只做两件事H5 把请求发给 Native Native 把结果回给 H5问题在于这两个动作都不是同步的。H5 调用window.myascf.send(ui.showToast,{message:hello from h5})它希望拿到的是一个 Promisewindow.myascf.send(ui.showToast,{message:hello from h5}).then(resconsole.log(res)).catch(errconsole.error(err))所以我们要设计一套协议让异步请求和异步响应可以对应起来。关键就是requestId。2. 请求协议H5 发给 ArkTS 的请求长这样{requestId:req_1700000000000_1,action:ui.showToast,params:{message:hello from h5}}字段不多但每个都很重要。requestId用来匹配响应。action表示要调用哪个能力。params是参数。如果没有requestIdH5 同时发出两个请求时就无法知道哪个响应属于哪个请求。3. H5 侧 send 方法H5 侧的send大致做这些事varcallbacksnewMap()window.myascf{send:function(action,params,options){returnnewPromise(function(resolve,reject){varrequestIdcreateRequestId()varrequest{requestId:requestId,action:action,params:params||{}}callbacks.set(requestId,{resolve:resolve,reject:reject,action:action,createdAt:Date.now()})window.MyASCFNative.postMessage(JSON.stringify(request))})}}这里有一个 callback map。它的作用是保存每一次请求对应的 Promise 回调。等 ArkTS 回来时再根据requestId找到它。4. ArkWeb 注入对象ArkTS 侧通过 JavaScriptProxy 向 H5 注入一个对象Web({src:$rawfile(web/index.html),controller:this.controller}).javaScriptProxy({object:this.nativeProxy,name:MyASCFNative,methodList:[postMessage],controller:this.controller})H5 侧就可以调用window.MyASCFNative.postMessage(JSON.stringify(request))这里的postMessage是 ArkTS 暴露出来的方法。5. JavaScriptProxy 只做转发JavaScriptProxy不应该写业务逻辑。它只负责把消息交给 BridgeController。exportclassJavaScriptProxy{constructor(privatebridgeController:BridgeController){}postMessage(message:string):void{this.bridgeController.handleMessage(message)}}这是一条很重要的边界。如果在 Proxy 里直接判断 action那么它很快就会变得混乱。Proxy 是入口不是业务层。6. ArkTS 返回响应ArkTS 返回给 H5 的响应格式如下{requestId:req_1700000000000_1,code:0,message:success,data:{echoAction:ui.showToast}}H5 暴露一个全局回调window.__myascf_on_native_response__function(responseText){varresponseJSON.parse(responseText)varcallbackcallbacks.get(response.requestId)if(!callback){console.warn(CALLBACK_LOST,response.requestId)return}callbacks.delete(response.requestId)if(response.code0){callback.resolve(response)}else{callback.reject(response)}}ArkTS 通过runJavaScript调用这个函数。7. 为什么要小心字符串转义ArkTS 回调 H5 时本质上是在执行一段 JS 字符串。比如window.__myascf_on_native_response__({...})如果 JSON 里有引号、换行或特殊字符脚本就可能拼坏。所以项目里抽出了BridgeCallbackExecutor统一负责JSON 序列化参数安全转义拼接 JS执行 runJavaScript记录日志。这样 BridgeController 就不需要关心字符串细节。8. 这一阶段的意义到这里我们还没有实现真正的 Toast。但是通信边界已经成立了H5 Promise → requestId → callback map → JavaScriptProxy → BridgeController → runJavaScript → H5 Promise resolve / reject这一步很重要。因为后面的 Dispatcher、Registry、Biz、Imp 都建立在这个边界之上。项目地址https://github.com/lichenyang5/MiniAppRuntime-Harmony