const res = await fetch('/api/users');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const users = await res.json();
const created = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Alice' }),
}).then(r => { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.json(); });
const controller = new AbortController();
const { signal } = controller;
fetch('/api/data', { signal })
.then(r => r.json())
.catch(err => {
if (err.name === 'AbortError') return;
throw err;
});
controller.abort();
controller.abort(new Error('User navigated away'));
async function fetchWithTimeout(url, ms = 5000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), ms);
try {
const res = await fetch(url, { signal: controller.signal });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} finally {
clearTimeout(id);
}
}
async function fetchWithRetry(url, options = {}, retries = 3) {
for (let attempt = 0; attempt < retries; attempt++) {
try {
const res = await fetch(url, options);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
if (err.name === 'AbortError' || attempt === retries - 1) throw err;
await new Promise(r => setTimeout(r, 2 ** attempt * 200));
}
}
}
async function streamText(url) {
const res = await fetch(url);
const reader = res.body.getReader();
const decoder = new TextDecoder();
let result = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
result += decoder.decode(value, { stream: true });
console.log('chunk:', decoder.decode(value));
}
return result;
}