Async/Await hibakezelés JavaScriptben: ne essünk csapdába API hívásoknál
Üdv a kódfronton! Ha már JavaScript-et írsz, valószínűleg találkoztál az async/await szintaxissal, ami átalakította, ahogy aszinkron műveletekkel dolgozunk. De amikor API hívásokról van szó, a hibakezelés gyakran a fejlesztők buktatója lesz. Ma részletezem, milyen mintákat érdemes követni, hogy kódunk ne dőljön össze, amikor a backend néha „nem érez jól”.
Miért fontos a szilárd hibakezelés?
Amikor fetch() vagy axios segítségével hívunk meg egy API-t, számos dolog mehet félre: hálózati probléma, 500-os szerverhiba, érvénytelen JSON válasz, vagy épp a felhasználó gyors megnyomja a frissítést. Az async/await szépen leegyszerűsíti az aszinkron kódot, de ha nem kezeljük explicit a hibákat, a felhasználó csupán egy „fekete lyukat” fog látni.
Az alapok: try-catch blokk
A legelterjedtebb minta a try...catch használata async függvényen belül:
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP hiba! Státusz: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('API hívás sikertelen:', error.message);
// Felhasználóbarát üzenet megjelenítése
showNotification('Az adatok betöltése sikertelen. Kérjük, próbáld újra.');
return null;
}
}A kulcsfontosságú rész itt az if (!response.ok) ellenőrzés. A fetch() csak hálózati hibákra dob kivételt, de a 404-es vagy 500-as státuszkódokat nem! Ezeket nekünk kell explicit kezelnünk.
Gyakori buktatók, amiket érdemes elkerülni
1. Elfelejtjük a response.ok ellenőrzést – Ez a legnagyobb hiba. A fetch sikeresnek tekint egy 404-es választ is, mert technikailag „kapottunk választ”.
2. Túl általános catch blokk – Ne csak logoljunk, hanem típusonként különböző kezelést alkalmazzunk.
3. Nincs timeout kezelés – Az API hívások néha „lelógnak”. Érdemes timeout-ot beállítani:
async function fetchWithTimeout(url, timeout = 8000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
throw new Error('A kérés túllépte az időkeretet');
}
throw error;
}
}Integráció PHP backenddel és jQuery frontenddel
Nézzünk egy teljesebb példát, ahol PHP backenddel és jQuery/Bootstrap frontenddel dolgozunk:
Backend (PHP):
query('SELECT id, name, price FROM products WHERE active = 1');
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
http_response_code(200);
echo json_encode(['success' => true, 'data' => $products]);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'Szerverhiba történt']);
}
?>Frontend (jQuery + Bootstrap + JavaScript):
async function loadProducts() {
// Bootstrap loading state
$('#product-list').html(`
<div class="text-center my-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Betöltés...</span>
</div>
</div>
`);
try {
const response = await $.ajax({
url: '/api/get_products.php',
method: 'GET',
dataType: 'json',
timeout: 10000
});
if (!response.success) {
throw new Error(response.error || 'Ismeretlen hiba');
}
renderProducts(response.data);
} catch (error) {
let errorMessage = 'A termékek betöltése sikertelen.';
if (error.status === 404) {
errorMessage = 'Az API végpont nem található.';
} else if (error.status === 500) {
errorMessage = 'Szerverhiba. Kérjük, próbáld később.';
} else if (error.statusText === 'timeout') {
errorMessage = 'A kérés túl sokáig tart. Ellenőrizd az internetkapcsolatot.';
}
// Bootstrap alert megjelenítése
$('#product-list').html(`
<div class="alert alert-danger alert-dismissible fade show" role="alert">
${errorMessage}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
`);
}
}
function renderProducts(products) {
// SCSS/CSS stílusozott megjelenítés
const html = products.map(product => `
<div class="product-card card shadow-sm mb-3">
<div class="card-body">
<h5 class="card-title">${product.name}</h5>
<p class="card-text text-primary fw-bold">${product.price} Ft</p>
</div>
</div>
`).join('');
$('#product-list').html(html);
}
// Oldal betöltésekor
$(document).ready(function() {
loadProducts();
// Frissítés gomb
$('#refresh-btn').on('click', loadProducts);
});Haladó minta: újrapróbálkozás (retry logic)
Néha érdemes adott hibák esetén újrapróbálkozni, pl. hálózati időtúllépésnél:
async function fetchWithRetry(url, maxRetries = 3) {
let lastError;
for (let i = 0; i setTimeout(resolve, 1000));
continue;
}
break;
}
}
throw lastError;
}Összegzés
Az async/await hibakezelése API hívásoknál nem csak technikai kérdés, hanem felhasználói élménybeli is. A legfontosabb tanácsok:
1. Mindig kezeld a HTTP státuszkódokat (response.ok)
2. Használj specifikus hibakezelést a különböző hibafajtákra
3. Jelzés a felhasználónak – Bootstrap alert, spinner, vagy más visszajelzés
4. Időtúllépés kezelése kötelező
5. Érdemes logolni a hibákat (fejlesztéshez), de a felhasználónak emberbarát üzenetet mutatni
Ne feledd: a jó hibakezelés nem csak a kód stabilitását növeli, hanem azt is jelzi a felhasználóknak, hogy alkalmazásod professzionális és megbízható. Legközelebb, amikor API-t hívsz, kérdezd meg magadtól: „Mi történik, ha minden szétesik?” – és írd meg a választ kódban.
Boldog hibakezelést!