JavaScript · API · Просунутий
Обробка помилок
Надійно обробляйте HTTP-помилки та збої мережі за допомогою response.ok і try/catch.
Короткий вступ до теми та пояснення перед вправами (вправи нижче):
Практичні паттерни обробки помилок
#Довідник обробки помилок
#Вправи:
Перевірити response.ok
#const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// запит до неіснуючого товару — вивести status і ok
// запит до реального товару — вивести status і ok
}
main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
const r1 = await fetch(`${BASE_URL}/api/products/99999/`);
console.log(r1.status, r1.ok); // 404 false
const r2 = await fetch(`${BASE_URL}/api/products/1/`);
console.log(r2.status, r2.ok); // 200 true
}
main();
Кинути виняток при HTTP-помилці
#const BASE_URL = 'https://apilearn.tukas.dev';
async function getProduct(id) {
// fetch, перевірити response.ok, кинути виняток якщо не ok
}
async function main() {
// викликати з дійсним id
// викликати з 99999 і перехопити помилку
}
main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';
async function getProduct(id) {
const response = await fetch(`${BASE_URL}/api/products/${id}/`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
async function main() {
try {
const p = await getProduct(1);
console.log(p.name);
} catch (err) {
console.log('Error:', err.message);
}
try {
await getProduct(99999);
} catch (err) {
console.log('Error:', err.message); // HTTP 404
}
}
main();
Обробити 401 Unauthorized
#const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// запит профілю без авторизації, окрема обробка 401
}
main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
const response = await fetch(`${BASE_URL}/api/users/profile/`);
if (response.status === 401) {
console.log('Unauthorized — provide a valid token');
} else if (!response.ok) {
console.log(`HTTP error: ${response.status}`);
} else {
const data = await response.json();
console.log(data.username);
}
}
main();
Обгортка safeFetch
#const BASE_URL = 'https://apilearn.tukas.dev';
async function safeFetch(url) {
// fetch, перевірити ok, повернути json або null
}
async function main() {
const good = await safeFetch(`${BASE_URL}/api/products/1/`);
console.log(good ? good.name : 'null');
const bad = await safeFetch(`${BASE_URL}/api/products/99999/`);
console.log(bad);
}
main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';
async function safeFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) {
console.error(`HTTP ${response.status} for ${url}`);
return null;
}
return response.json();
} catch (err) {
console.error('Network error:', err.message);
return null;
}
}
async function main() {
const good = await safeFetch(`${BASE_URL}/api/products/1/`);
console.log(good ? good.name : 'null');
const bad = await safeFetch(`${BASE_URL}/api/products/99999/`);
console.log(bad);
}
main();
Таймаут через AbortController
#const BASE_URL = 'https://apilearn.tukas.dev';
async function fetchWithTimeout(url, ms = 3000) {
// використати AbortController для переривання через ms мілісекунд
}
async function main() {
const data = await fetchWithTimeout(`${BASE_URL}/api/products/`, 5000);
console.log(data ? data.count : 'timed out');
}
main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';
async function fetchWithTimeout(url, ms = 3000) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), ms);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timer);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
} catch (err) {
if (err.name === 'AbortError') {
console.log('Request timed out');
return null;
}
throw err;
}
}
async function main() {
const data = await fetchWithTimeout(`${BASE_URL}/api/products/`, 5000);
console.log(data ? data.count : 'timed out');
}
main();