到第五篇为止,画面想知道最新的值就得去问——每秒问一次,或者靠人刷新。
告诉它
改完值之后加一行。
waiting -= n;
_save(waiting);
// Say that it changed. Not what it changed to.
server.notifyResourceUpdated('desk://waiting');
放一个可订阅的资源,并在 capability 里打开 subscribe: true。
resources: ResourcesCapability(listChanged: true, subscribe: true),
出到线上的东西
{"jsonrpc":"2.0","method":"notifications/resources/updated","params":{"uri":"desk://waiting"}}
只有 uri。 变成几个人,不在里面。
为什么不能把值带上
把值放进通知看着理所当然——一趟就完了。可是 通知不保证顺序。
服务端:waiting 变成 2 → 发通知 A
服务端:waiting 变成 1 → 发通知 B
客户端:B 先到 (1) → A 后到 (2) ← 顺序翻了
画面:2
一旦带了值,晚到的旧通知就会覆盖新值。 画面悄悄显示了错的数字,而没人知道。
只发「变了」,这个问题就消失了。不管来几次、什么顺序,接的一方去读,拿到的就是 那一刻的最新值。
后厨屏那篇得出过同样的结论。那时是设计上的选择,这里则是包本身只这么发——notifyResourceUpdated(uri) 根本没有放值的位置。
没订阅就什么都不出去
做的时候卡住过。notifyResourceUpdated 调了,服务端日志也打了,线上却什么都没有。
notified desk://waiting ← 服务端确实调了
(客户端这边什么也没有)
因为不会发给没有订阅的客户端。 这是规范。
{"jsonrpc":"2.0","id":2,"method":"resources/subscribe","params":{"uri":"desk://waiting"}}
发过这一句之后才会来。这是个很容易误当成服务端缺陷的地方——服务端是对的,是接的一方没做准备。
校验 —— 解析出来看有没有带值
ask step6 \
'{"jsonrpc":"2.0","id":2,"method":"resources/subscribe","params":{"uri":"desk://waiting"}}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"desk.admit","arguments":{"count":1}}}'
params = json.loads(lines[0]).get('params', {})
extra = set(params) - {'uri'}
if extra:
print('the notification carried', sorted(extra), '— it must carry only the uri')
sys.exit(1)
一开始用 grep waiting 来查,结果误报。uri 本身就是 desk://waiting,所以永远会中。不能按字符串看,得解析出来看键。
notification params: {"uri": "desk://waiting"}
step6 notification carried the uri and no value