ネットワーク再試行
このキットの他のエラー契約はすべて、レスポンスが届いたことを前提に
しています —
エラーマップは
ステータスコードでルーティングします。このレシピはステータスが
そもそも存在しないケースを所有します: 機内モード、切断された
ソケット、宣言したタイムアウト。htmx はこれを htmx:sendError /
htmx:timeout として通知しますが、このレシピがなければページは
黙って飲み込みます — 保存を押したのに何も起きない、あれです。
別名: オフライン対応、タイムアウト再試行。
フォームは 1.5 秒のタイムアウトを宣言しています。Simulate
offline にチェックが入っているとエンドポイントはそれより長く
眠るので、リクエストはタイムアウトし、再試行アラートが現れます。
チェックを外して Retry を押してください: リクエストは現在の
入力値を集め直して成功し、アラートは自分で消えます。
エンドポイントは api/recipes/network-retry/ 配下の名前空間化された
デモ実装です — 「down」フレーバーは宣言済みタイムアウトより長く
待つだけです。本物のネットワーク障害だけは、サーバから送ることが
できないからです。
マークアップ
Section titled “マークアップ”<!-- One host per page, client-owned, empty in source --><div data-hc-network-retry></div>
<form method="post" action="/orders" data-hx-post="/orders" data-hx-request='{"timeout": 10000}' data-hx-target="#order-result" data-hx-swap="innerHTML" data-hx-disabled-elt="find button[type=submit]"> <input type="hidden" name="idempotency_key" value="ik_7d1f9c2e"> <!-- …フィールド… --> <button class="hc-button" data-variant="primary" type="submit">Place order</button></form>
<div id="order-result" aria-live="polite"></div>installNetworkRetry() は behaviors バンドルが自動インストール
します。ホストはスワップターゲットの外に置いてください — ホストを
置き換えるスワップはバナーを消してしまいます。
- なぜこれだけ JavaScript か: 「サーバがバリデータであり
語り手である」の唯一の例外 — ネットワーク障害には語りの元になる
サーバレスポンスがありません。クライアントがここだけは i18n
カタログ(
networkRetry.failed/networkRetry.retry。ホストのdata-hc-network-retry-message/-labelで上書き可)を通じて 語ります。 - タイムアウトはデフォルトではなく宣言:
要素ごとに
data-hx-request='{"timeout": 10000}'、または グローバルにhtmx.config.timeout。宣言がなければハードな送信 失敗だけが発火します — htmx の方針をそのまま維持。 - 失敗時: behavior は失敗したリクエストを記憶し(1 スロット、
最新勝ち —
セッション切れ再認証
と同じ方針)、ホストに
hc-alert(role="status")を 1 つ描画 します。失敗が繰り返されてもその場で再描画 — 積み上げません。 - Retry はバイト単位のリプレイではなく新しい試行:
htmx.ajax(verb, path, { source })を values 上書きなしで発行 するので、クリック時点の入力値を集め直します。パイプライン全体が 再実行されます — CSRF ヘッダー、インジケーター、ターゲット解決。 - 本物のレスポンスが来たらクリア: 失敗した要素上の成功または
エラー — ステータスのあるエラーはエラーマップの管轄で、
このバナーの管轄ではありません。失敗自身の
status: 0では 決してクリアしません。 - 決して自動再試行しない。 再試行はユーザーの動詞です。確認なしの
POST 自動再試行は二重注文の作り方そのものです。ポーラー
(
every …)はどのみち次のティックで自己回復します。
Retry × 冪等キー
Section titled “Retry × 冪等キー”看板の組み合わせです。「ネットワークが死ぬ前に、最初のクリックは 届いていたのか?」 — 冪等キーが フォームに隠れていれば、答えはどちらでも安全です: 再試行された POST は同じキーを集め直すので、元のリクエストがコミット済みで レスポンスだけが失われていた場合、再試行には元のレスポンスが リプレイされます。キーなしの再試行 POST は正真正銘の二重送信 リスクです — 必ずペアで。
プログレッシブエンハンスメント
Section titled “プログレッシブエンハンスメント”JS オフは htmx オフ、つまりフルページ遷移です — ブラウザ自身の ネットワークエラーページがハンドラで、リロードボタンも付いて います。ホストは空のまま見えません。
アクセシビリティ
Section titled “アクセシビリティ”描画されるアラートは role="status"(polite)です: ユーザーは
たった今操作してページを見ています。Retry ボタンは通常のタブ順に
入る本物の <button>。失敗が繰り返されても同じアラートを再描画し、
読み上げを積み上げません。ホストに自分で aria-live を付けないで
ください — behavior のアラートが既にロールを持っています。
- 冪等キー — POST の再試行をサーバ側で安全にするもの。
- セッション切れ再認証 — 同じ記憶して再実行の機構。こちらは 401 起点。
- エラーと復旧 — このレシピが「ステータスなし」行で完成させるステータスコード マップ。