ASCF WebView:H5 为什么收不到元服务消息?

ASCF WebView:H5 为什么收不到元服务消息?

H5 调用 postMessage 后返回 success 和 complete,却没有触发 onMessage,是元服务 WebView 通信里最容易误判的问题之一。

关键结论:H5 发送成功只证明 H5 -> 元服务 可用;要验证 元服务 -> H5,必须由元服务使用 has.createWebViewContext().postMessage 发送,并由 H5 的 has.ascfweb.onMessage 接收。

官方参考:WebView 开发 - 元服务服务框架(ASCF)

两条方向,三类 API

方向 发送端 接收端 不能证明什么
H5 -> 元服务 has.ascfweb.postMessage web-view 的 bindmessage 不能证明元服务能向 H5 发消息
元服务 -> H5 has.createWebViewContext().postMessage has.ascfweb.onMessage 这是本文验证的方向

因此,如果 H5 侧打印:

复制代码
postMessage success {}
postMessage complete {}

这只能说明 H5 -> 元服务 成功;并不能说明 H5 的 onMessage 已收到元服务消息。

版本边界:不要混淆三个版本

层级 本文版本/要求 含义
ASCF 框架 2.0.4+ 官方 API 页面明确标注:has.ascfweb.onMessage 的起始版本为 2.0.4。
H5 JS SDK @atomicservice/ascf-web-sdk 1.0.8 本次真机验证实际使用的 H5 SDK。
元服务 API 包 @atomicservice/ascfapi:声明 ^1.0.6,锁定 1.0.23 元服务 ohpm 依赖。
HarmonyOS SDK 5.0.0(12) 本最小复现工程的 compatibleSdkVersion 和 targetSdkVersion。

重点:

  • has.ascfweb.onMessage 从 ASCF 框架 2.0.4 起支持;低于该版本时不应调用此 API。
  • ASCF 框架 2.0.4+ 不等于 H5 JS SDK 2.0.4。
  • 本文没有把 2.0.4 写到 H5 script 地址中;H5 使用的是 1.0.8。
  • ASCF 运行时 versionCode 不是框架语义化版本,不能拿它替代 2.0.4 的版本判断。

H5 正确写法:初始化时注册接收回调

服务端 H5 页面引入 JS SDK 后,尽早注册回调:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>PostMessage H5</title>
  <script src="ascf-web-sdk.umd.js"></script>
</head>
<body>
  <h1>H5 - has.ascfweb.onMessage</h1>
</body>
<script>
  has.ascfweb.onMessage((data) => {
    console.info('onMessage H5收到来自元服务的消息:', data);
  });
</script>
</html>

监听应放在 H5 初始化阶段,而不是接口请求、按钮点击或延迟定时器之后。不要假设回调注册前的消息会被缓存后补发。

为了看清对象内容,调试时可以额外打印:

js 复制代码
has.ascfweb.onMessage((data) => {
  console.info('H5 received:', JSON.stringify(data));
});

设备控制台把对象显示为 object Object 时,表示回调已收到对象但日志被字符串化,不代表消息失败。

元服务正确写法:使用 WebView 上下文发送

hxml

xml 复制代码
<view class="menu-list">
  <view class="web-view-class">
    <web-view src="{{ url }}"
      bindmessage="onWebviewMessage"
      class="web-view-class"></web-view>
  </view>
  <button bindtap="sendString" type="primary">发送字符串</button>
  <button bindtap="sendSimpleObject" type="primary">发送简单对象消息</button>
</view>

css

css 复制代码
.web-view-class {
  height: 400px;
}

.menu-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 16px;
}

WebView 不能占满整个不可滚动页面,否则原生按钮会被挤出屏幕,表象会变成"发送函数没执行"。

js

js 复制代码
Page({
  data: {
    url: 'https://www.example.com/example.html',
  },

  onWebviewMessage(event) {
    console.info('onWebviewMessage:', JSON.stringify(event));
  },

  sendString() {
    const ctx = has.createWebViewContext();
    ctx.postMessage({
      data: 'Js string message to H5',
      success: () => console.info('postMessage success'),
      fail: (err) => console.error('postMessage fail:', err),
      complete: (res) => console.info('postMessage complete:', res),
    });
  },

  sendSimpleObject() {
    const ctx = has.createWebViewContext();
    ctx.postMessage({
      data: {
        msg: 'JS object message to H5',
        version: '1.0',
      },
      success: () => console.info('postMessage success'),
      fail: (err) => console.error('postMessage fail:', err),
      complete: (res) => console.info('postMessage complete:', res),
    });
  },
});

这里有两个不可替代的关键点:

  1. 调用 has.createWebViewContext() 获取当前 WebView 控制实例。
  2. 调用 ctx.postMessage({ data: ... });业务消息放在 data 字段。

常见错误路径

1. 把 H5 发送成功当作双向成功

H5 的 has.ascfweb.postMessage 成功,验证的只是 H5 -> 元服务。要测试 H5 接收,必须让元服务调用 ctx.postMessage。

2. 未按 ASCF 场景使用 createWebViewContext

不要用其他 WebView 框架的元素实例调用方式替代官方场景中的 has.createWebViewContext().postMessage。发送端可能没有进入 ASCF 的桥接通道。

3. H5 注册 onMessage 过晚

回调未注册时发送消息,不能假设运行时会缓存并补发。因此先注册监听,再执行其它业务初始化。

4. 发送按钮不可见或不可点击

WebView 固定高度过大、页面不能滚动时,按钮在视口之外,元服务侧自然不会出现 postMessage success、fail、complete 日志。

5. URL 被域名管控拦截

H5 必须先被 WebView 成功加载。局域网 HTTP 调试地址若被域名管控拦截或出现 ERR_ABORTED,应先处理服务器域名配置;开发期可按平台规则启用"开发中元服务豁免管控"。

真机验证证据

最小示例在真机上得到:

css 复制代码
onMessage H5收到来自元服务的消息: Js string message to H5
postMessage success
postMessage complete: {}

onMessage H5收到来自元服务的消息: [object Object]
postMessage success
postMessage complete: {}

结论:

  • 字符串消息已由元服务发送,并触发 H5 的 onMessage。
  • 简单对象也已触发 onMessage;对象日志显示为 object Object 属于展示形式。
  • 发送端的 success / complete 与 H5 接收日志同时出现,才是元服务 -> H5 通信成功的完整证据。

发布前检查清单

  • ASCF 框架版本为 2.0.4 或更高;has.ascfweb.onMessage 的官方起始版本是 2.0.4。
  • H5 引入正确版本的 ascf-web-sdk.umd.js。
  • H5 初始化时注册 has.ascfweb.onMessage。
  • 元服务使用 has.createWebViewContext().postMessage({ data })。
  • 元服务记录 success、fail、complete。
  • H5 URL 已通过正式域名管控或调试豁免。
  • WebView 不遮挡发送按钮。

总结

把通信方向拆开,就不会被单侧 success 误导:

css 复制代码
H5 -> 元服务:has.ascfweb.postMessage
元服务 -> H5:has.createWebViewContext().postMessage({ data })
H5 接收:has.ascfweb.onMessage

按官方 WebView 场景使用上下文 API,并确保 ASCF 框架版本满足 2.0.4+ 的能力要求后,H5 可以稳定接收元服务发送的字符串和简单对象消息。

相关推荐
flash俊杰7 小时前
ASR 转写与字幕时间轴:强制对齐、CPS 约束与 SRT 工程化
前端
前端炒粉7 小时前
AI工具面经
前端
唐小码7 小时前
裁员的风刮到了三线荒凉的城市
前端
晚安日记wanna7 小时前
React 为何不做双端 diff?Vue 与 React 更新逻辑的三层差异
前端·react.js·面试
flash俊杰7 小时前
AI 分段引擎与自动剪辑决策:从语义片段到时间线草稿的映射
前端·ai编程
flash俊杰8 小时前
时间线交互引擎:从像素到帧的逆向映射与磁吸网格
前端
光影少年8 小时前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
flash俊杰8 小时前
LLM 结构化输出的契约化工程:JSON Mode、Schema 约束与重试降级
前端·ai编程
༄久梦༒长醉༻8 小时前
AI面试助手:本地运行,一键备战
前端·ai编程
Web4Browser8 小时前
浏览器指纹逆向到底在分析什么:从 JavaScript 采集、Canvas 与 WebGL 到环境一致性校验
java·服务器·前端