Загрузка…
Загрузка…
HTTP / REST · middle · сложность 6
Branch on status class; Idempotency-Key on POST; content negotiation via Accept/Content-Type; fetch не throws на errors.
// Content negotiation + explicit contract awareness
const res = await fetch('/api/orders', {
method: 'POST', // NOT idempotent — guard against double-submit
headers: {
'Content-Type': 'application/json', // what I'm SENDING
'Accept': 'application/json', // what I want BACK
'Idempotency-Key': crypto.randomUUID(), // make POST safe to retry
},
body: JSON.stringify({ sku: 'A1', qty: 2 }),
});
// ✅ Branch on the STATUS CLASS, not just res.ok
if (res.status === 201) {
const location = res.headers.get('Location'); // where the new resource lives
} else if (res.status === 409) {
// conflict — someone else changed it; refetch and merge, don't blindly retry
} else if (res.status === 429) {
const retryAfter = Number(res.headers.get('Retry-After')) || 1; // seconds
// back off, THEN retry
} else if (res.status >= 500) {
// server fault — safe to retry with backoff for idempotent methods
}// ❌ fetch does NOT throw on 404/500 — this hides real failures
const data = await fetch(url).then(r => r.json()); // parses an error page as JSON
// ✅ check res.ok yourself
const r = await fetch(url);
if (!r.ok) throw new Error(`HTTP ${r.status}`);Explicit status handling + idempotency on POST — minimum bar for production HTTP client code.