- HTTP sorğusunu və cavabını izah etmək: metod, URL, başlıqlar, gövdə, status kodu
fetchilə GET və POST sorğuları göndərmək, JSON oxumaq, HTTP və şəbəkə xətalarını düzgün emal etmək- Etibarlı asinxron şablonlar qurmaq: vaxt limiti, təkrar cəhd, paralel sorğular və
URLSearchParams
Tətbiqdəki hava proqnozu, valyuta məzənnələri, sosial şəbəkədəki lent — hamısı serverlərdən API vasitəsilə gəlir. Sənin kodun HTTP sorğusu göndərir, server isə verilənlərlə, adətən JSON ilə cavab verir. fetch bunun üçün brauzerlərdə və Node.js-də (18-ci versiyadan) hazır olan müasir alətdir.
Bir dəqiqədə HTTP
Sorğu metoddan, URL-dən, başlıqlardan (headers) və bəzən gövdədən (body) ibarətdir. Cavabda status kodu, başlıqlar və gövdə olur. Status kodunun birinci rəqəmi mənanı verir: 2xx — uğur, 3xx — yönləndirmə, 4xx — müştərinin xətası (səhv sorğu), 5xx — serverin xətası.
POST /api/orders HTTP/1.1
Host: shop.example.com
Content-Type: application/json
Authorization: Bearer <token>
{"productId": 7, "quantity": 2}
HTTP/1.1 201 Created
Content-Type: application/json
{"id": 1043, "productId": 7, "quantity": 2, "status": "new"}API qurmaq üslubu: verilənlər öz URL-i olan resurslardır (/users, /users/42), əməliyyatlar isə HTTP metodları ilə ifadə olunur. Hər sorğu müstəqildir (server əvvəlki sorğunu «xatırlamır»), verilənlər adətən JSON kimi ötürülür.
| Metod | Mənası | Nümunə və uğurlu cavab |
|---|---|---|
| GET | oxumaq | GET /users/42 → 200 OK |
| POST | yaratmaq | POST /orders → 201 Created |
| PUT / PATCH | tam / qismən yeniləmək | PATCH /users/42 → 200 OK |
| DELETE | silmək | DELETE /orders/1043 → 204 No Content |
fetch ilə GET
fetch(url) Response obyekti ilə yerinə yetirilən Promise qaytarır. İş iki addımdır: əvvəl cavabı gözləyirsən (başlıqlar gəlir), sonra gövdəni response.json() ilə oxuyursan — bu da Promise-dir. Vacib məqam: fetch yalnız şəbəkə xətasında (internet yoxdur, domen tapılmır, CORS) rədd olunur. 404 və 500 cavabları da uğurla «gəlir», ona görə response.ok-u (status 200–299) həmişə yoxla.
async function getUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
}
try {
const user = await getUser(42);
console.log(user.name, user.city);
await getUser(999999);
} catch (error) {
console.log('Request failed:', error.message);
}Aysel Baku Request failed: HTTP 404
api.example.com şərti ünvandır: real API-də sahələrin adları fərqli olacaq. Bu səhifədəki icraçı real sorğu göndərmir, ona görə aşağıda serveri təqlid edəcəyik.Response obyektini JavaScript-in özündə yaratmaq olar. Bu, serveri təqlid etməyə və internetsiz məşq etməyə imkan verir: fakeFetch real fetch kimi Response qaytarır, sənin kodun isə fərqi hiss etmir. Testlərdə də məhz belə edirlər.
const db = { 42: { id: 42, name: 'Aysel', city: 'Baku' } };
async function fakeFetch(url) {
await new Promise((resolve) => setTimeout(resolve, 50));
const id = Number(url.split('/').pop());
const user = db[id];
return new Response(JSON.stringify(user ?? { error: 'Not found' }), {
status: user ? 200 : 404,
headers: { 'Content-Type': 'application/json' },
});
}
for (const id of [42, 7]) {
const response = await fakeFetch(`/api/users/${id}`);
console.log(response.status, response.ok, response.headers.get('content-type'));
console.log(await response.json());
}▸ Gözlənilən nəticə
200 true application/json
{ id: 42, name: 'Aysel', city: 'Baku' }
404 false application/json
{ error: 'Not found' }POST, başlıqlar və xətalar
Verilən göndərmək üçün fetch-ə ikinci arqument kimi seçimlər obyekti verilir: method, headers və body. Gövdə mətn olmalıdır, ona görə obyekt JSON.stringify ilə sətrə çevrilir, Content-Type: application/json başlığı isə serverə formatı bildirir. Giriş tələb edən API-lər adətən Authorization: Bearer <token> başlığını gözləyir.
async function createOrder(order, token) {
const response = await fetch('https://api.example.com/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(order),
});
if (response.status === 401) throw new Error('Please log in again');
if (!response.ok) throw new Error(`Server error ${response.status}`);
return response.json();
}
const saved = await createOrder({ productId: 7, quantity: 2 }, token);
console.log('Created order', saved.id, saved.status);Created order 1043 new
Etibarlı asinxron şablonlar
Real şəbəkə yavaş və etibarsızdır. Dörd vərdiş kömək edir: sorğu parametrlərini URL və URLSearchParams ilə qur (xüsusi simvollar avtomatik kodlaşdırılır); asılı olmayan sorğuları Promise.all ilə paralel göndər; vaxt limiti qoy — fetch(url, { signal: AbortSignal.timeout(8000) }) 8 saniyədən sonra sorğunu TimeoutError ilə ləğv edir; müvəqqəti xətalarda (5xx, 429) fasiləni artıraraq təkrar cəhd et.
const url = new URL('https://api.example.com/search');
url.searchParams.set('q', 'plov & dolma');
url.searchParams.set('city', 'Baku');
url.searchParams.set('page', 2);
console.log(url.toString());
console.log(url.searchParams.get('q'));
console.log(Object.fromEntries(url.searchParams));▸ Gözlənilən nəticə
https://api.example.com/search?q=plov+%26+dolma&city=Baku&page=2
plov & dolma
{ q: 'plov & dolma', city: 'Baku', page: '2' }?q=plov & dolma sorğunu pozardı: & yeni parametr kimi başa düşülərdi. URLSearchParams onu %26 kimi kodlaşdırır.function slowServer(ms, signal) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => resolve('data'), ms);
signal.addEventListener('abort', () => {
clearTimeout(timer);
reject(new DOMException('Request took too long', 'TimeoutError'));
});
});
}
async function withTimeout(ms, limit) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), limit);
try {
return await slowServer(ms, controller.signal);
} catch (error) {
return `failed: ${error.name}`;
} finally {
clearTimeout(timer);
}
}
console.log(await withTimeout(50, 200));
console.log(await withTimeout(500, 200));▸ Gözlənilən nəticə
data failed: TimeoutError
AbortController ləğv siqnalı yaradır; real fetch bu signal-ı qəbul edir. AbortSignal.timeout(ms) eyni işi bir sətirdə görür.getJSON(url) köməkçisini yaz: o, fakeFetch(url)-i çağırsın, cavab uğurlu deyilsə, HTTP <status> mesajlı xəta atsın, uğurludursa, JSON-u qaytarsın.
const products = { 1: { id: 1, title: 'Notebook', price: 5 } };
async function fakeFetch(url) {
const id = Number(url.split('/').pop());
const product = products[id];
return new Response(JSON.stringify(product ?? { error: 'Not found' }), {
status: product ? 200 : 404,
headers: { 'Content-Type': 'application/json' },
});
}
async function getJSON(url) {
// call fakeFetch, check response.ok, return the JSON
}
for (const url of ['/api/products/1', '/api/products/99']) {
try {
console.log(await getJSON(url));
} catch (error) {
console.log('Error:', error.message);
}
}▸ Gözlənilən nəticə
{ id: 1, title: 'Notebook', price: 5 }
Error: HTTP 404flakyFetch ilk iki dəfə 503 qaytarır. fetchWithRetry(url, retries) funksiyasını yaz: uğursuz hər cəhddə Attempt N: 503 çap etsin, 5xx xətasında 100, sonra 200 ms (hər dəfə iki qat) gözləyib yenidən cəhd etsin, retries təkrar bitəndə və ya 4xx-də isə HTTP <status> xətası atsın.
let calls = 0;
async function flakyFetch(url) {
calls++;
const ok = calls >= 3;
return new Response(JSON.stringify(ok ? { rates: { USD: 1.7 } } : {}), { status: ok ? 200 : 503 });
}
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function fetchWithRetry(url, retries) {
// only one attempt for now: add retries with a growing delay
const response = await flakyFetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
const data = await fetchWithRetry('/api/rates', 3);
console.log('Rates:', data.rates);▸ Gözlənilən nəticə
Attempt 1: 503
Attempt 2: 503
Rates: { USD: 1.7 }Əsas fikirlər
- HTTP: sorğu = metod + URL + başlıqlar + gövdə; cavab = status + başlıqlar + gövdə. 2xx uğur, 4xx müştəri xətası, 5xx server xətası.
- REST: resurslar URL-lərdədir, əməliyyatlar metodlarla: GET oxuyur, POST yaradır, PUT/PATCH yeniləyir, DELETE silir.
fetchyalnız şəbəkə xətasında rədd olunur — həmişəresponse.ok-u yoxla, gövdəniawait response.json()ilə bir dəfə oxu.- POST üçün
method,Content-Type: application/jsonbaşlığı vəbody: JSON.stringify(data)göndər. - Etibarlılıq: vaxt limiti (
AbortSignal.timeout), müvəqqəti 5xx xətalarında təkrar cəhd, paralel sorğular üçünPromise.all, parametrlər üçünURLSearchParams.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.
fetch göndərilir. Nə baş verir?