064. Queueing(キューイング:リクエストの「順番待ち」戦略を決める)
原理:通信の渋滞をどう解決するか?
リクエストが重なった時のジレンマ
Webアプリを操作していると、次のようなことが起こります。 「サーバーからの返事がまだ届いていないのに、ユーザーが次のボタンを押してしまった!」
このとき、HTMX(ブラウザ)はどう振る舞うべきでしょうか? 1. 古い通信は捨てて、新しい方を優先する? 2. 今の通信が終わるまで、新しい方は無視(拒否)する? 3. 列に並べて、今の通信が終わってから順番に実行する?
この「順番待ちのルール」を決めるのが 「Queueing(キューイング)戦略」 です。デフォルトでは、HTMXは「新しいリクエストが来たら、まだ終わっていない古いリクエストをキャンセルする」という、非常に現代的な(せっかちな)設定になっています。
実践:状況に合わせた「待ち方」の指定
1. 「前のはいいから、次をお願い!」(デフォルト:drop)
検索窓などではこれが最適です。古いキーワードの結果を今さらもらっても困るからです。
<!-- 何も書かなければ、新しい通信が始まると古いのは自動的に止まります (queue:last) -->
<input hx-get="/search" hx-trigger="keyup delay:200ms">
2. 「終わるまで、次のボタンは押させない!」(拒否:none)
二重登録を防ぎたい決済ボタンや保存ボタンに向いています。
<!--
queue:none : 今の通信が終わるまで、次のクリックは無視されます。
-->
<button hx-post="/api/pay" hx-request='{"queue": "none"}'>
決済する
</button>
3. 「順番に全部処理して!」(並べる:first/all)
ログの送信や、確実に順番通りに実行してほしい一連のアクションに向いています。
<!--
queue:first : 最初の通信が終わるまで、あとのリクエストを「予約(列の先頭)」に入れておきます。
-->
<button hx-post="/api/log" hx-request='{"queue": "first"}'>
ログ送信
</button>
4. ステップ・バイ・ステップ解説
- 想定外の連打を予測: 「今の通信が終わる前にユーザーが何かしたら困るかな?」と考えます。
- 戦略を選ぶ:
last(デフォルト): 常に最新志向。古いのは捨てる。first: 最初の通信を大事にする。あとの一つは待機。none: 二回目は受け付けない。all: 全部順番にやる。
- 属性の記述:
hx-request='{"queue": "戦略名"}'と書き込みます。
比較:どの「並び方」が正解か?
| 戦略 | 古い通信の扱い | 新しい通信の扱い | おすすめ用途 |
|---|---|---|---|
| last (標準) | キャンセルする | 即座に実行 | 検索、タブ切り替え |
| none | 最後まで通す | 無視する | 登録、削除、決済 |
| first | 最後まで通す | 1つだけ予約 | データの保存、並び替え |
| all | 全部通す | 全部予約 | 送信ログ、チャットの連投 |
まとめ:初心者のための「交通整理」の判断基準
「キューイング」なんて難しそうな言葉ですが、要は「リクエスト同士が喧嘩しないように仲裁するルール」のことです。
- 迷ったらデフォルトでOK: HTMXのデフォルト(
last)は、多くのモダンなWebアプリにとって最も「サクサク」感じる設定になっています。 - 「保存」には
noneを: 二重送信はバグの温床です。大切なボタンにはqueue: "none"を添えてあげましょう。 - ユーザーを不安にさせない: 通信待ちの間は
hx-indicator(035.ローダー)を出して、「今頑張ってるからちょっと待ってね」と伝えることもセットで忘れずに。
リクエストの渋滞を、技術でスマートに解消する。queue を使いこなして、複数の操作が重なっても動じない、誠実でタフなWebアプリを構築してください。第3章の最後を飾るのは、送信前に「内容をチェック」して止める「リクエスト・フィルタリング(065. Request Filtering)」です。