← ユースケース

ポーリングをリアルタイム更新に置き換える

数秒ごとに 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)にできます。
  • イベントのサイズはプランによって異なります。料金をご覧ください。
  • 配信前に何人が見ているか知りたい場合は、オンライン人数をご覧ください。