4 編目まで、最新の値を知るには問わねばならなかった。一秒ごとに問うか、人が更新するか。
購読する
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 ひとつだ。何人になったかは来ない。サーバー 6 編目で値を載せない理由を扱ったが、受ける側ではそれが 読まねばならない という意味になる。
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 だった瞬間を見ていない。 最終値だけが必要なら構わないが、「0 になったら通知」のような規則があれば、その規則は発動しない。
間隔を縮めても消えない。狭くなるだけだ。そして狭めるほど無駄が増える。
終わったら解く
await client.unsubscribeResource('desk://waiting');
画面が閉じたら購読を解く。解かなければサーバーが居ない相手に送り続ける。
実機の編の ESP32 はこれを 画面定義の中に 入れていた — onReady で購読、onDestroy で解除。生命周期が画面に書かれていれば、クライアントは忘れられない。