Fetch API — HTTP so'rovlar, headers, method, body
Muammodan boshlaylik
Siz ro'yxatdan o'tish formasini yozdingiz. Foydalanuvchi "Ro'yxatdan o'tish" tugmasini bosdi.
Eski usulda HTML <form> sahifani to'liq yangilardi — ma'lumot serverga ketadi, server yangi sahifani qaytaradi, brauzer qayta yuklanadi. Har safar to'liq yangilanish.
Zamonaviy ilovalar bunday ishlamaydi. Instagram da yangi post yozsangiz — sahifa yangilanmaydi. Twitter da like bossangiz — faqat o'sha tugma o'zgaradi. Server bilan sahifani yangilamay muloqot qilish mumkin.
Buning uchun — Fetch API.
Fetch nima?
Fetch — brauzerga o'rnatilgan vosita. JavaScript orqali serverga HTTP so'rov yuborish va javob olish uchun.
Sahifa yangilanmaydi. Foydalanuvchi hech narsani sezmaydi — fon da so'rov ketadi, javob keladi, faqat kerakli qism yangilanadi.
Hayotiy o'xshatma
Tasavvur qiling: siz ofisdasiz. Hamkasbingizdan hujjat kerak. Eski usul — o'zingiz turib, uning xonasiga borasiz, hujjatni olasiz, qaytasiz — bu vaqtda boshqa hech narsa qila olmaysiz.
Zamonaviy usul — kuryer yuborasiz. "Mana manzil, mana nima kerak" deb aytasiz. Kuryer ketadi. Siz esa ishingizni davom ettirasiz. Hujjat kelganida kuryer xabar beradi.
fetch — o'sha kuryer. Siz so'rov yuboriysiz, sahifa ishlashda davom etadi, javob kelganida kod ishga tushadi.
Eng oddiy fetch
fetch("https://jsonplaceholder.typicode.com/users/1")
.then(function(javob) {
return javob.json();
})
.then(function(foydalanuvchi) {
console.log(foydalanuvchi.name);
});
Bu uch qadam:
fetch(url)— so'rov yuborildi, Promise qaytarildi.then(javob => javob.json())— javob keldi, JSON ga o'girildi.then(data => ...)— ma'lumot tayyor, ishlatish mumkin
Nima uchun ikkita .then()? Bu muhim savol.
Nima uchun javob.json() ham await kerak?
fetch muvaffaqiyatli bo'lganda qaytaradigan narsa — to'liq ma'lumot emas. U Response ob'ekti — "javob keldi" degan signal. Ma'lumot hali oqim (stream) ko'rinishida kelmoqda.
Hayotiy o'xshatma
Kuryer eshikni taqillatti — bu birinchi signal: "keldi". Lekin qo'lingizda hali hujjat yo'q. Eshikni ochib, hujjatni kuryer qo'lidan olish — ikkinchi qadam. Bu qadam ham vaqt oladi.
fetch — eshikni taqillatish. .json() — hujjatni qo'lga olish. Ikkalasi asinxron.
const javob = await fetch("/api/users"); // ← eshik taqilladi — javob keldi
// javob.ok, javob.status — bilish mumkin
// lekin ma'lumot hali olinmagan
const data = await javob.json(); // ← hujjat qo'lga olindi
// endi data bilan ishlash mumkin
Async/Await bilan fetch
async function foydalanuvchiOlish(id) {
const javob = await fetch(`/api/users/${id}`);
const data = await javob.json();
return data;
}
Qisqa va o'qish oson. Bundan keyingi misollar shu uslubda yoziladi.
HTTP metodlar — nima uchun turli metodlar bor?
Serverga so'rov yuborilganda — faqat manzil emas, niyat ham bildiriladi. Bu niyat HTTP metod orqali ifodalanadi.
Hayotiy o'xshatma
Kutubxona. Siz ham kitob olishingiz mumkin, ham yangi kitob topshirishingiz, ham mavjud kitobni almashtira olasiz. Barchasi kutubxona bilan muloqot — lekin har xil niyat. HTTP metodlar — o'sha niyat.
GET — "menga ma'lumot ber". Serverda hech narsa o'zgarmaydi. Brauzer manzil satrida URL yozganda — GET.
POST — "yangi narsa yarataman". Ma'lumot body da yuboriladi.
PUT — "mavjud narsani to'liq almashtiraman". Barcha maydonlar yuboriladi.
PATCH — "mavjud narsaning bir qismini o'zgartiraman". Faqat o'zgargan maydonlar.
DELETE — "o'chiraman".
Default — GET. Boshqa metodlar uchun method parametri ko'rsatiladi.
POST — yangi ma'lumot yuborish
Serverga ma'lumot yuborish uchun uchta narsa kerak: metod, headers va body.
async function foydalanuvchiYarat(ism, email) {
const javob = await fetch("/api/users", {
method: "POST", // ← niyat: yangi yaratish
headers: {
"Content-Type": "application/json", // ← body JSON formatida
},
body: JSON.stringify({ ism, email }), // ← yuborilayotgan ma'lumot
});
const yangi = await javob.json();
return yangi;
}
Nima uchun JSON.stringify?
Tarmoq orqali faqat matn yuborish mumkin. JavaScript ob'ekti — matn emas. JSON.stringify ob'ektni JSON matnga o'giradi:
{ ism: "Jasur", email: "jasur@mail.com" }
↓ JSON.stringify
'{"ism":"Jasur","email":"jasur@mail.com"}'
Server bu matnni oladi va o'z tomonida ob'ektga qaytaradi.
Nima uchun Content-Type header?
Server qabul qilayotgan matni qanday formatda ekanini bilishi kerak. application/json — "men senda JSON yuboryapman, shunday o'qi". Bu header bo'lmasa — server body ni nima ekanini bilmaydi.
Boshqa metodlar
PUT va PATCH — POST ga o'xshash, faqat metod o'zgaradi:
// Foydalanuvchini to'liq yangilash
async function yangilash(id, yangiMalumot) {
const javob = await fetch(`/api/users/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(yangiMalumot),
});
return javob.json();
}
// O'chirish
async function ochirish(id) {
const javob = await fetch(`/api/users/${id}`, {
method: "DELETE",
});
return javob.ok; // true yoki false
}
Headers — so'rov haqida qo'shimcha ma'lumot
Header — "konvert yozuvi". Xat ichida asosiy ma'lumot, konvertda esa — kimga, qayerdan, qanday yuborilayotgani.
Eng ko'p ishlatiladigan headerlar:
Content-Type — body qanday formatda. Yuqorida ko'rdik.
Authorization — siz kimsiz. Serverga "men avvalroq login qilganman, mana mening tokenim" deb aytish uchun.
async function himoyalangan_malumot() {
const token = localStorage.getItem("token");
const javob = await fetch("/api/profile", {
headers: {
"Authorization": `Bearer ${token}`, // ← "men kimsizligim mana"
"Content-Type": "application/json",
},
});
return javob.json();
}
Accept — "men qanday formatda javob kutayapman". Ko'pincha application/json.
javob.ok — muvaffaqiyatmi?
Bu eng muhim va ko'p e'tibor berilmaydigan narsa.
fetch — tarmoq xatosida reject qiladi: internet yo'q, server topilmadi. Lekin server 404 Not Found yoki 500 Internal Server Error qaytarsa — fetch reject qilmaydi. Server javob berdi — bu tarmoq nuqtai nazaridan muvaffaqiyat.
Demak bu kod xato:
// ❌ — server 404 qaytarsa ham catch ga tushmaydi
async function foydalanuvchiOlish(id) {
try {
const javob = await fetch(`/api/users/${id}`);
return await javob.json(); // ← 404 javobini ham JSON ga o'girishga urinar
} catch (xato) {
console.error(xato); // faqat tarmoq uzilsa ishlaydi
}
}
To'g'risi — javob.ok ni tekshirish:
// ✅ — javob.ok tekshirildi
async function foydalanuvchiOlish(id) {
const javob = await fetch(`/api/users/${id}`);
if (!javob.ok) {
// javob.status — 404, 403, 500 va hokazo
throw new Error(`Server xatosi: ${javob.status}`);
}
return javob.json();
}
javob.ok — status 200–299 orasida bo'lsa true. Boshqa holatlarda false.
Tez-tez uchraydigan xatolar
javob.json() ni kutmaslik:
const javob = await fetch("/api/users");
const data = javob.json(); // ❌ await yo'q — data = Promise
const data2 = await javob.json(); // ✅
JSON.stringify unutish — POST da:
// ❌ — ob'ekt to'g'ridan body ga berildi
await fetch("/api/users", {
method: "POST",
body: { ism: "Jasur" }, // ob'ekt, matn emas — server tushunmaydi
});
// ✅
await fetch("/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ism: "Jasur" }),
});
Content-Type headersiz POST yuborish:
Server body ni oladi, lekin qanday formatda ekanini bilmaydi. Ko'pchilik server frameworklari body ni umuman ko'rinmaydi — bo'sh keladi.
// ❌ — Content-Type yo'q
await fetch("/api/users", {
method: "POST",
body: JSON.stringify({ ism: "Jasur" }),
});
// ✅
await fetch("/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" }, // ← shart
body: JSON.stringify({ ism: "Jasur" }),
});
fetch 404 ni xato deb hisoblamasligini unutish:
Bu eng xavfli xato. Dastur ishlaydi, hech qanday xato ko'rinmaydi — lekin aslida ma'lumot kelmagan.
// ❌ — 404 bo'lsa ham "muvaffaqiyatli" ishlaydi
const javob = await fetch("/api/user/999");
const data = await javob.json(); // {"message": "Not found"} — xato xabar, lekin xato ko'rinmaydi
// ✅ — har doim javob.ok tekshiriladi
const javob = await fetch("/api/user/999");
if (!javob.ok) throw new Error(`${javob.status}`);
const data = await javob.json();
Xulosa
Fetch — JavaScript dan serverga HTTP so'rov yuborish. Sahifa yangilanmaydi.
Har doim ikkita await: birinchi — fetch uchun (javob kelishini kutish), ikkinchi — .json() uchun (ma'lumotni oqimdan olish).
GET — olish, body shart emas. POST/PUT/PATCH — yuborish, body va Content-Type header kerak. DELETE — o'chirish.
javob.ok — har doim tekshiriladi. fetch 404, 500 da reject qilmaydi — bu dasturchi qo'li bilan tekshiriladi.
Keyingi dars
42-dars: Fetch API — xatolarni ushlash, loading holati, AbortController