消息广播 messaging
messaging 是发布/订阅风格的事件广播:一次 emit,所有已连接面板(跨插件,不按 appid 过滤)、当前小程序的全部逻辑层插件、渲染层都能收到。挂在三个全局变量上(wadLogicLayer.messaging / wadRenderLayer.messaging / wadPanelLayer.messaging),三层 API 一致。
发送者信息在 meta 里带上 —— 发送者自己也会收到自己的消息(回声),由接收方按 meta 过滤。注意:顶层 emit 主要投递本插件面板;面板发出的 emit 还会派发到同插件逻辑层。完整跨层广播用 messaging。
本页你将学到
emit → Promise<payload>的返回语义;meta信封的全部字段;- 回声过滤与 eventId 去重的标准写法;
- 面板 → 逻辑层 → 面板的完整管线实战。
emit(name, data)
广播到当前小程序的全部三层(跨插件可见)。
- 签名:
emit(name, data) → Promise<payload>(resolve 发出的载荷) data必须可 JSON 序列化;建议 ≤ 64KB(总线帧有大小限制)。
js
(async () => {
const sent = await wadPanelLayer.messaging.emit('scan-done', { count: 42 });
// sent.data.count === 42;sent 是完整 payload(含 name/from/eventId/at…)
})();on(name, fn)
订阅。回调签名 fn(data, meta)。
js
wadPanelLayer.messaging.on('scan-done', function (data, meta) {
if (meta.from === 'panel' && meta.plugin === wadPanelLayer.id) return; // 过滤本层回声
render(data.count);
});meta 字段:
| 字段 | 说明 |
|---|---|
from | 'logic' | 'render' | 'panel' |
instanceId | 发送方实例(面板为总线 clientId;逻辑层固定 'logic';渲染层为 render-xxxxxx) |
plugin | 发送方插件 id |
eventId | 面板 emit 由宿主生成 m<序号>;逻辑层保留发送方 me<序号>-<ts>;渲染层本地返回值与广播副本 id 不同 |
at | 时间戳 |
once(name, fn)
收到一次即自动注销。
js
wadPanelLayer.messaging.once('ready-signal', function (data) { start(data); });off(name, fn)
解绑,要传同一个函数引用。
js
function handler(d) { /* ... */ }
wadPanelLayer.messaging.on('tick', handler);
wadPanelLayer.messaging.off('tick', handler);onAny(fn)
监听所有事件名,回调 fn(name, data, meta);返回解绑函数。
js
const un = wadPanelLayer.messaging.onAny(function (name, data, meta) {
log.push(`[${meta.from}/${meta.plugin}] ${name}`);
});
un(); // 停止回声过滤模式
发送者也会收到自己的消息,推荐统一过滤写法:
js
wadPanelLayer.messaging.on('my-event', function (data, meta) {
// 只处理「其他来源」的消息
if (meta.plugin === wadPanelLayer.id && meta.from === 'panel') return;
handle(data);
});也可以用 eventId 去重(逻辑/面板可靠;渲染层本地返回值与广播副本 id 不同,不能只靠 eventId):
| 写法 | 做法 |
|---|---|
| 按 from 过滤 | meta.from === 本层 时 return |
| 按 eventId 去重 | 记录已处理的 eventId,重复直接跳过 |
| 多面板去回声 | meta.instanceId === wadPanelLayer.clientId 时 return |
作用域
- 广播范围 = 所有已连接面板(跨插件,不按 appid 过滤)+ 当前小程序全部逻辑层插件 + 渲染层
- 切换小程序后旧面板仍可能收到(面板按连接而不是按 appid 过滤)
- 换到别的小程序收不到;要跨小程序持久共享数据用 sharedStorage 的
global作用域
实战:面板按钮 → 逻辑层执行 → 结果广播回面板
js
(async () => {
// —— 逻辑层:注册技能并广播进度 ——
wadLogicLayer.register('scan', function () {
let i = 0;
const t = setInterval(function () {
i += 10;
wadLogicLayer.messaging.emit('scan-progress', { pct: i });
if (i >= 100) { clearInterval(t); wadLogicLayer.messaging.emit('scan-done', { items: 42 }); }
}, 200);
return true;
});
// —— 面板:触发 + 收进度(过滤面板自己 emit 的回声) ——
button.onclick = async function () {
await wadPanelLayer.logicLayer.call('scan'); // 可变参:不传参就不写
};
wadPanelLayer.messaging.on('scan-progress', function (d, meta) {
if (meta.from !== 'logic') return;
bar.style.width = d.pct + '%';
});
wadPanelLayer.messaging.on('scan-done', function (d, meta) {
if (meta.from !== 'logic') return;
show(d.items);
});
})();实战:渲染层 ↔ 逻辑层
js
// —— 渲染层:用户点了页面元素 ——
document.querySelector('#buy').onclick = function () {
wadRenderLayer.messaging.emit('ui-tap', { id: 'buy' });
};
// —— 逻辑层:接住并改数据 ——
wadLogicLayer.messaging.on('ui-tap', function (d, meta) {
if (meta.from !== 'render') return;
wadLogicLayer.http.post('https://api.example.com/tap', d);
});messaging vs sharedStorage
事件(发生了什么,一次性)用 messaging;状态(当前值是什么,要能读回)用 sharedStorage。两者常配合:emit 通知 + sharedStorage 存底。