
Contents
1) fetch のエラーハンドリング&リトライ
要点は3つ:
- HTTPエラーは
res.okを見る(200–299 以外は例外扱い) - ネットワーク/タイムアウト/5xx をリトライ(4xxは通常リトライしない)
- タイムアウト+指数バックオフ+ジッターで“優しく再試行”
サンプルでは api.js に fetchWithRetry(url, options, { retries, backoff, factor, jitter, timeout, retryOn }) を実装。retryOn で「どんな失敗を再試行するか」を関数で指定できます。
// 使い方(main.js)
const data = await fetchWithRetry(
`https://jsonplaceholder.typicode.com/posts?_limit=${limit}`,
{},
{
retries: 3, backoff: 500, factor: 2, jitter: true, timeout: 7000,
retryOn: (err) => err?.message === 'Request timeout'
|| err instanceof TypeError // ネットワークなど
|| (err?.status >= 500) // サーバ5xx
}
);
2) ES Modules でファイル分割
役割ごとに小さく:
api.js… 通信とリトライvalidation.js… 入力チェック(純粋関数にしてテストしやすく)dom.js… DOMユーティリティmain.js… イベント配線&画面更新(副作用を集約)
HTML は <script type="module" src="./main.js"></script>。main.js 内で import { fetchWithRetry } from './api.js' のように読み込みます。
3) フォームのバリデーション & 軽いテスト
入力チェックは純粋関数で:validateSignup({ name, email }) => errors[]。
UI側はそれを呼んで表示を切り替えるだけにします。
// validation.js
export function isNonEmpty(s){ return typeof s==='string' && s.trim().length>0; }
export function isEmail(s){ return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test((s||'').trim()); }
export function validateSignup({name,email}){
const errors=[]; if(!isNonEmpty(name)) errors.push('お名前を入力してください');
if(!isEmail(email)) errors.push('メールアドレスの形式が正しくありません');
return errors;
}
console.assert で“壊れていないか”をさくっと確認:
console.assert(isNonEmpty('abc') === true);
console.assert(isEmail('a@b.com') === true);
console.assert(validateSignup({name:'', email:'bad'}).length >= 1);
失敗すると Console に赤字で出ます。まずはこのレベルのテストを日常に。
画面で試せること
- 「投稿を読み込む」:通信成功/失敗/リトライの流れと、ステータス表示を体験
- サインアップ風フォーム:必須チェック&メール形式 → OKなら成功メッセージ
- Console を開くと
console.assertの小テストログが見られます
次の一歩(お好みで)
fetchWithRetryに 「特定のHTTPコードだけ再試行」(429, 503)を追加- フォームに HTML標準の Constraint Validation API(
input.reportValidity()など)を併用 - モジュールを ディレクトリごとに分け、
index.jsで再エクスポート - とくに失敗しやすい関数だけ Jest なしの“関数単体テストHTML” を別途用意









