到第四篇为止,想知道最新的值就得去问——每秒问一次,或者靠人刷新。
订阅
client.onResourceUpdated((uri) {
// The notification says only that it changed. Read to learn what to.
seen.add(uri);
stdout.writeln('notified: $uri');
});
await client.subscribeResource('desk://waiting');
然后让值真的变一下。
await client.callTool('desk.admit', {'count': 1});
subscribed to desk://waiting
notified: desk://waiting
after the notification, reading gives {waiting: 2}
notifications received: 1
通知只带 uri
处理器收到的是一个 uri。变成几个人不会来。服务端第六篇讲了为什么不带值;在接收这一侧,它的意思就是 你必须去读。
final now = await client.readResource('desk://waiting');
多走一趟看着吃亏,可这样永远是对的。不管来几条通知、什么顺序,读的那一刻的值 就是最新的。
轮询真正的问题
拒绝轮询的理由通常是成本。每秒敲一次服务端是浪费。
那是次要的。真正的问题是,你看不到两次询问之间。
09:00:00 轮询 → waiting 3
09:00:00.4 进来两个 → waiting 1
09:00:00.7 来了一个 → waiting 2
09:00:01 轮询 → waiting 2
画面从 3 到了 2。它没看到曾经是 1 的那一刻。 如果只要最终值,无所谓;可要是有「归零就报警」这类规则,那条规则永远不会触发。
把间隔调小也消不掉,只是变窄。而越窄,浪费越大。
结束就退订
await client.unsubscribeResource('desk://waiting');
画面关掉就退订。不退,服务端会一直往一个不存在的对象发。
真板那篇里的 ESP32 把这件事放进了 画面定义里 —— onReady 订阅,onDestroy 解除。生命周期写在画面上,客户端就忘不掉。