ポーリングをリアルタイム更新に置き換える
数秒ごとに API へ問い合わせるのをやめ、変化を一度だけ送ります。リクエストとサーバー負荷を減らし、変化はその瞬間に表示されます。
多くのアプリは「問い合わせ」で変化を知ります。開いているページが数秒ごとに API を呼び、注文やチケット、レポートが変わったかを確かめるのです。答えはほとんど「変化なし」なのに、そのたびにリクエスト、データベースのクエリ、ユーザーのスマートフォンのバッテリーを使い、実際の変化も次の間隔まで画面に出ません。Hibira なら、変化が起きたときにサーバーが一度だけ送り、そのデータを表示しているすべてのページが数ミリ秒で更新されます。
ユーザーが得るもの
- 最大 5 秒待つことなく、変化が起きた瞬間に画面に表示。
- 再読み込みなしで、どのタブも常に最新。
- スマートフォンが数秒ごとに無駄に通信しなくなる。
ポーリングのコスト
1,000 人がページを開いたまま 5 秒ごとにポーリングすると、1 時間で 720,000 リクエストになります。その 1 時間にデータが 200 回しか変わらなければ、99.97% のリクエストは新しい内容を返しません。プッシュなら同じ 1 時間は 200 メッセージで済み、API が処理するのは各ページの最初の読み込みだけです。
使う機能
- プライベートチャンネル(
private-order-42)。ページに表示するものごとに 1 つ用意し、サーバーが認可するので、ユーザーには自分のデータだけが届きます。 - 公式サーバー SDK の
trigger。変更を保存した直後に呼びます。 pusher:subscription_succeeded。最初の接続時と再接続のたびに発火するので、現在の状態を読み込むタイミングに最適です。
ポーリング
開いているすべてのページ5 秒ごと
GET /api/orders/42
APIほとんど「変化なし」
プッシュ
API変更を保存
trigger() を一度Hibira
WebSocket
表示しているすべてのページすぐに更新
ステップ 1:ポーリングのループを見つける
たいていこのような形です:
setInterval(async () => {
render(await fetch('/api/orders/42').then((r) => r.json()));
}, 5000);ステップ 2:一度読み込み、あとは待ち受ける
JavaScript ガイドのとおりに接続し、プライベートチャンネル用の認可エンドポイントを用意します。購読の準備ができたら現在の状態を読み込み、その後は変化が届くたびに反映します:
const load = async () => render(await fetch('/api/orders/42').then((r) => r.json()));
const channel = pusher.subscribe('private-order-42');
channel.bind('pusher:subscription_succeeded', load);
channel.bind('updated', (order) => render(order));ステップ 3:保存したときに変化を送る
データが変わる場所(API ルート、ワーカー、管理画面の操作、Webhook)で、書き込みが成功したあとに配信します:
app.patch('/api/orders/:id', requireLogin, async (req, res) => {
const order = await db.orders.update(req.params.id, req.body);
await pusher.trigger(`private-order-${order.id}`, 'updated', order);
res.json(order);
});ステップ 4:軽い保険を残す
再接続後に購読がもう一度発火するので、接続が切れていた間の抜けは load() が埋めてくれます。ブラウザーはバックグラウンドのタブを凍結することもあるため、タブが前面に戻ったときにも一度読み込みます:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') load();
});ヒント
- 再描画に必要な内容を送ります。大きなデータは ID とバージョンだけ送り、残りはページに取得させます。
- 同じデータが毎秒何度も変わる場合は、リアルタイムダッシュボードのようにまとめて送ります。
- 頻繁に変わる一覧は、行ごとではなく一覧ごとに 1 チャンネル(
private-orders-team-7)にできます。 - イベントのサイズはプランによって異なります。料金をご覧ください。
- 配信前に何人が見ているか知りたい場合は、オンライン人数をご覧ください。