Fetch API — HTTP so'rovlar, headers, method, body

~20 daq · JavaScript · Asinxron JavaScript

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:

  1. fetch(url) — so'rov yuborildi, Promise qaytarildi
  2. .then(javob => javob.json()) — javob keldi, JSON ga o'girildi
  3. .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