Skill:把插件能力暴露成技能
Skill = 用 wad.register(name, fn) 注册到逻辑层的具名函数。
它是插件的「对外能力面」:面板、渲染层、宿主,甚至其他调试工具,都通过 wad.logic.call(name, ...args) 调用它。
定义
html
<script type="text/wad-logic">
// ① 纯函数
wad.register('add', function (a, b) { return a + b; });
// ② 读业务数据
wad.register('cart.items', function () {
return wx.getStorageSync('cart_items') || [];
});
// ③ 带参数与校验
wad.register('order.find', function (id) {
if (!id) throw new Error('缺少订单号');
return wx.getStorageSync('order_' + id) || null;
});
// ④ 异步:先受理,用事件推回
wad.register('location.now', function () {
wx.getLocation({
success: function (res) { wad.emit('location.now:done', res); },
fail: function (e) { wad.emit('location.now:done', { error: e.errMsg }); }
});
return 'accepted';
});
</script>调用
面板:
js
const sum = await wad.logic.call('add', 1, 2);
const items = await wad.logic.call('cart.items');
const order = await wad.logic.call('order.find', 'A1001'); // 无效参数 → reject
// 异步 Skill:call 拿受理标记,事件拿结果
const ack = await wad.logic.call('location.now'); // 'accepted'
wad.on('location.now:done', function (loc) { render(loc); });渲染层:
js
// 没有 wx,但可以调逻辑层 Skill
wad.logic.call('cart.items').then(function (items) {
document.querySelector('#count').textContent = items.length;
});错误语义
| 场景 | 调用方收到 |
|---|---|
| 函数未注册 | e.code = 'HOST_ERROR',message 含 Skill 名 |
| 函数内 throw | e.code = 'HOST_ERROR',message 为原始异常 |
| 6s 无响应 | e.code = 'TIMEOUT' |
| 参数 / 返回超过 200KB | e.code = 'SEND_FAILED' |
js
wad.logic.call('order.find').catch(function (e) {
// e.code === 'HOST_ERROR'
// e.message === '缺少订单号'
wad.ui.toast(e.message);
});命名建议
- 用插件前缀:
tokenwatch.last、geofence.current; - 一个插件暴露 3~8 个高内聚 Skill,粒度对齐「面板上的一个功能」;
- Skill 内不要做长耗时循环,阻塞逻辑层会卡住小程序;
- 只读写自己的命名空间或业务只读数据,不要互相写。
实战: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 src="/ui/plugin-sdk.js"></script>
<script>
wad.ready.then(function () {
refresh();
wad.on('storageWrite', function (e) {
if (e.key.indexOf('token') >= 0) refresh();
});
});
function refresh() {
wad.logic.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">
wad.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>