插件多层函数注册
插件多层函数 = 用 wadLogicLayer.register(name, fn) 注册到逻辑层的具名函数。
它把插件能力暴露给三个方向:
- 面板按钮 →
wadPanelLayer.logicLayer.call(name, ...args) - 渲染层脚本 →
wadRenderLayer.logicLayer.call(name, ...args) - 逻辑层自身 →
wadLogicLayer.call(name, ...args)(同步直调)
call 统一使用可变参:call('add', 1, 2)。
本页你将学到
- register 的四种注册形态(同步/校验/异步受理);
- 三层调用这些函数的写法差异(可变参统一);
- 错误语义与命名建议;
- 一个完整的 Key 监控插件。
定义(逻辑层)
html
<script type="text/wad-logic">
// ① 纯函数:同步返回 JSON 可序列化值
wadLogicLayer.register('add', function (a, b) { return a + b; });
// ② 读业务数据
wadLogicLayer.register('cart.items', function () {
return wx.getStorageSync('cart_items') || [];
});
// ③ 带参数 + 校验
wadLogicLayer.register('order.find', function (id) {
if (!id) throw new Error('缺少订单号'); // 调用方收到 Error: 缺少订单号(e.code==='ERROR')
return wx.getStorageSync('order_' + id) || null;
});
// ④ 异步结果:先受理,用事件推回(register 不支持 Promise 返回)
wadLogicLayer.register('location.now', function () {
wx.getLocation({
success: function (res) { wadLogicLayer.messaging.emit('location.now:done', res); },
fail: function (e) { wadLogicLayer.messaging.emit('location.now:done', { error: e.errMsg }); }
});
return 'accepted'; // 立即返回受理标记
});
</script>调用(面板)
call 统一可变参:参数逐个展开,数组就是一个普通参数。
js
(async () => {
const sum = await wadPanelLayer.logicLayer.call('add', 1, 2); // 参数逐个展开
const items = await wadPanelLayer.logicLayer.call('cart.items');
const order = await wadPanelLayer.logicLayer.call('order.find', 'A1001'); // 无效参数 → reject
// 异步函数的约定:call 拿受理标记,事件拿结果
const ack = await wadPanelLayer.logicLayer.call('location.now'); // 'accepted'
wadPanelLayer.on('location.now:done', function (loc) { render(loc); });
})();调用(渲染层)
js
// 渲染层没有 wx,但可以调逻辑层函数(参数同样逐个展开)
wadRenderLayer.logicLayer.call('cart.items').then(function (items) {
document.querySelector('#count').textContent = items.length;
});调用(逻辑层本地)
本层直调,同步返回:
js
// <script type="text/wad-logic"> 内
var n = wadLogicLayer.call('add', 1, 2); // 3,可变参同步直调
var r = wadLogicLayer.call('sumAll', [1, 2, 3]); // 数组就是一个普通参数错误语义
| 场景 | 调用方收到 |
|---|---|
| 函数未注册 | Error: no function: <name>(e.code==='ERROR';本地 call 抛 E_CALL) |
| 函数内 throw | Error: <message>(e.code==='ERROR') |
| 超时(6s 无响应) | TIMEOUT |
| 参数/返回超过 200KB | 面板出站 >200KB 会排队并最终 TIMEOUT;宿主入站 >256KB 返回 frame_too_large |
js
wadPanelLayer.logicLayer.call('order.find').catch(function (e) {
// e.message === 'Error: 缺少订单号'
wadPanelLayer.ui.toast(e.message);
});约定:
- 返回值必须 JSON 可序列化(对象/数组/字符串/数字/布尔);
Promise返回值视为null(不要用它做异步返回,用事件推回);- 同名重复注册:后注册覆盖先注册。
命名建议
- 用插件前缀:
tokenwatch.last、geofence.current; - 一个插件暴露 3~8 个高内聚函数,粒度对齐「面板上一个功能」;
- 函数内不要做长耗时循环(阻塞逻辑层 JS 线程会卡小程序);
- 函数只读写本插件命名空间或业务只读数据,不要互相写。
实战示例:API Key 监控插件(完整)
html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="wad:package" content="keywatch">
<meta name="wad:name" content="Key 监控">
<meta name="wad:version" content="1.0.0">
</head>
<body>
<div id="out">等待中…</div>
<script>
wadPanelLayer.ready.then(function () {
refresh();
wadPanelLayer.on('storageWrite', function (e) {
if (e.key.indexOf('token') >= 0) refresh();
});
});
function refresh() {
wadPanelLayer.logicLayer.call('keywatch.scan').then(function (keys) {
document.getElementById('out').textContent = keys.length
? keys.join('\n') : '未发现 token 类 key';
}).catch(function (e) { document.getElementById('out').textContent = e.message; });
}
</script>
<script type="text/wad-logic">
wadLogicLayer.register('keywatch.scan', function () {
const info = wx.getStorageInfoSync();
return (info.keys || []).filter(function (k) {
return /token|auth|session/i.test(k);
}).map(function (k) { return k + ' = ' + String(wx.getStorageSync(k)).slice(0, 24); });
});
</script>
</body>
</html>