Mundarija (38)
- Bu darsda
- 1. Nega bu kerak?
- 2. Qisqa takrorlash: HTTP so'rov va javob
- 3. «Bahor» mashq API'si
- 3.1 Bu nima?
- 3.2 Brauzerda oching
- 4. Birinchi fetch
- 4.1 fetch Promise qaytaradi
- 4.2 await bilan javobni kutamiz
- 4.3 Nega ikkita await?
- 4.4 Event loop'da fetch
- 5. Response obyekti
- 5.1 Asosiy xususiyatlar
- 5.2 Tanani o'qish usullari
- 6. Eng muhim tuzoq: 404 da fetch xato bermaydi
- 6.1 HTTP xatosi — bu ham javob
- 6.2 ok ni tekshiring
- 6.3 Server xato haqida nima dedi?
- 7. Tarmoq xatosi: fetch qachon rad etiladi
- 7.1 Javob umuman kelmasa
- 7.2 Ikki xil xato — ikki xil ushlash
- 8. Sahifada: yuklanmoqda, ma'lumot, xato
- 8.1 DevTools'da so'rovni ko'ring
- 9. Node'da fetch
- 10. Hujumchi nigohi
- 11. Ko'p uchraydigan xatolar
- 11.1 await ni unutish
- 11.2 ok ni tekshirmaslik
- 11.3 HTML'ni json() bilan o'qish
- 11.4 Tanani ikki marta o'qish
- 11.5 Nisbiy yoki chala URL
- 12. Mashqlar
- 1-mashq (oson): Mantining narxi
- 2-mashq (o'rta): Ichimliklar ro'yxati
- 3-mashq (qiyin): Sahifalab olish
- 13. Real ishda
- Xulosa
- Manbalar
JavaScript fetch: serverdan ma'lumot olish, response.ok va json()
Qisqacha:
fetch(url)serverga HTTP so'rov yuboradi va Promise qaytaradi. UResponseobyekti bilan bajariladi; ma'lumotni olish uchun yana bittaawaitkerak:await javob.json(). Muhim tuzoq: 404 yoki 500 javobidafetchxato bermaydi —javob.okni o'zingiz tekshirasiz.fetchfaqat tarmoq umuman ishlamaganda rad etiladi.
Bu darsda
- «Bahor» mashq API'si nima ekanini bilasiz va undan haqiqiy ma'lumot olasiz.
fetchbilan so'rov yuborib, javobnijson()yokitext()bilan o'qiy olasiz.Responseobyektiningstatus,ok,headersxususiyatlarini ishlata olasiz.- HTTP xatosi (404, 500) bilan tarmoq xatosini farqlaysiz va ikkalasini to'g'ri ushlaysiz.
- Sahifada "yuklanmoqda → ma'lumot yoki xato" holatlarini ko'rsata olasiz.
Oldin bilishingiz kerak: HTTP metodlari va status kodlari, HTTP sarlavhalari, JSON asoslari, async / await, Dinamik import() va top-level await.
1. Nega bu kerak?
«Bahor» saytidagi menyu hozir HTML ichida qo'lda yozilgan. Tasavvur qiling: Jasur aka oshning narxini 35 000 dan 36 000 ga ko'tarmoqchi. Endi stajyor dasturchi Sardor HTML faylni ochib, raqamni topib, saytni qayta joylashi kerak. Telegram botda ham, kassadagi ekranda ham menyu bor — u yerda ham alohida o'zgartirish kerak.
Real loyihalarda bunday qilinmaydi. Menyu bitta joyda — serverda saqlanadi. Sayt, bot va kassa uni kerak bo'lganda serverdan so'raydi. Narx serverda o'zgarsa, hamma joyda o'zgaradi.
Brauzerdagi JavaScript serverdan ma'lumotni qanday so'raydi? fetch bilan. Bu darsdan boshlab kodingiz birinchi marta haqiqiy tarmoq bilan ishlaydi: so'rov internet orqali serverga boradi va haqiqiy javob qaytadi.
Va bu — asinxron ishning eng tipik namunasi. Javob 50 ms da ham, 5 soniyada ham kelishi mumkin. Oldingi darslarda o'rgangan hamma narsa — event loop, Promise, await — aynan shu yerda ishga tushadi.
2. Qisqa takrorlash: HTTP so'rov va javob
HTTP metodlari va status kodlari darsida brauzer va server qanday "gaplashishini" ko'rgan edik. Eslab olamiz:
| Qism | So'rovda | Javobda |
|---|---|---|
| Birinchi qator | metod va manzil: GET /api/mashq/menyu |
status: 200 OK |
| Sarlavhalar | Accept, Content-Type ... |
Content-Type, Cache-Control ... |
| Tana (body) | yuboriladigan ma'lumot (GET da yo'q) |
asosiy ma'lumot: HTML, JSON, rasm |
Sarlavha (header) — xabar ustidagi Nom: qiymat yorlig'i (HTTP sarlavhalari). Tana (body) — xabarning ichidagi asosiy ma'lumot. Status kodlari oilalari: 2xx — muvaffaqiyat, 3xx — yo'naltirish, 4xx — mijoz xatosi, 5xx — server xatosi.
Brauzer sahifa ochganda bularni o'zi qiladi. fetch esa xuddi shu so'rovni sizning kodingizdan yuborish imkonini beradi.
3. «Bahor» mashq API'si
3.1 Bu nima?
So'rov yuborish uchun server kerak. Shuning uchun IlmHamroh shu kurs uchun maxsus server tayyorlagan — «Bahor» mashq API'si:
https://ilmhamroh.uz/api/mashqAPI (Application Programming Interface) — dasturlar bir-biri bilan gaplashadigan "eshik". Veb API'da bu eshik — manzillar to'plami: har manzilga so'rov yuborasiz, u ma'lumot qaytaradi. Har bir shunday manzil endpoint (kirish nuqtasi) deb ataladi.
Bu server haqiqiy: u internetda ishlaydi va kodingiz unga xuddi katta kompaniyalarning API'lariga kabi murojaat qiladi. Lekin u mashq uchun yasalgan:
- Ochiq. Ro'yxatdan o'tish, kalit yoki parol kerak emas.
- Deterministik. Bir xil so'rovga doim bir xil javob keladi — darsdagi natija sizda ham aynan shunday chiqadi.
- Xavfsiz. Hech narsani buzib qo'ymaysiz: server haqiqiy buyurtma qabul qilmaydi, faqat o'zini shunday ko'rsatadi.
- Chegarasi bor. Bitta kompyuterdan daqiqasiga 120 ta so'rov. Oshib ketsa, server
429(so'rovlar juda ko'p) qaytaradi — bir daqiqa kuting.
11-qism davomida biz faqat shu API bilan ishlaymiz: bugun menyu olamiz, keyingi darslarda bron yuboramiz, CORS'ni sinaymiz, tokenlar bilan kiramiz.
3.2 Brauzerda oching
Boshlash uchun kod ham shart emas. Brauzer manzil qatoriga yozing:
https://ilmhamroh.uz/api/mashq/menyu/1Ekranda shu matn chiqadi:
{"id":1,"nom":"Osh","narx":35000,"turkum":"taom"}Bu — JSON (JSON asoslari). Chrome tepada Pretty print belgisini ham ko'rsatadi: uni belgilasangiz, JSON qatorlarga bo'lib, chiroyli ko'rinadi.
https://ilmhamroh.uz/api/mashq ning o'zini ochsangiz, barcha endpoint'lar ro'yxatini ko'rasiz. Bugun bizga ikkitasi kerak:
| Endpoint | Nima qaytaradi |
|---|---|
GET /api/mashq/menyu |
butun menyu: 4 ta taom |
GET /api/mashq/menyu/:id |
bitta taom yoki 404 |
:id — o'rniga son qo'yiladigan joy: /menyu/1, /menyu/3. Shuningdek ?turkum=ichimlik (faqat ichimliklar) va ?kechikish=1000 (javobni 1 soniya kechiktirish — sekin internetni sinash uchun) sozlamalari bor.
Tekshirib ko'ring: Brauzerda
https://ilmhamroh.uz/api/mashq/menyu/99ni oching. Nima chiqadi va nega?
Javob
{"xato":"Taom topilmadi","id":99}. Menyuda 99-taom yo'q, server buni JSON bilan aytdi. Ko'rinmasa ham, javobning status kodi — 404. Uni bu darsda fetch bilan o'qiymiz.
4. Birinchi fetch
4.1 fetch Promise qaytaradi
fetch — brauzer (va Node 18+) beradigan funksiya: u berilgan manzilga HTTP so'rov yuboradi. U ham host API (Sinxron va asinxron kod darsidagi setTimeout kabi): so'rovni JavaScript emas, brauzer yoki Node yuboradi va javobni kutadi.
Javob darhol kelmaydi. Shuning uchun fetch natijani emas, Promise qaytaradi (Promise asoslari):
const vada = fetch("https://ilmhamroh.uz/api/mashq/menyu/1");
console.log(vada); // Promise { <pending> }<pending> — "kutilmoqda". So'rov yo'lda, javob hali yo'q.
Bu blok node bayroqli: Node Promise'ni shunday chiqaradi. Brauzer konsoli Promise {<pending>} deb biroz boshqacha yozadi — ma'nosi bir xil.
4.2 await bilan javobni kutamiz
Promise natijasini await bilan kutamiz (async / await):
async function oshniOl() {
const javob = await fetch("https://ilmhamroh.uz/api/mashq/menyu/1");
console.log(javob.status);
console.log(javob.ok);
const taom = await javob.json();
console.log(taom);
console.log(`${taom.nom}: ${taom.narx} so'm`);
}
oshniOl();Konsolda:
200
true
{ id: 1, nom: 'Osh', narx: 35000, turkum: 'taom' }
Osh: 35000 so'mQatorma-qator:
await fetch(...)— so'rov ketdi, javob kelguncha funksiya to'xtab turadi. Natija —Response(javob) obyekti.javob.status— status kodi:200.javob.ok— status 200–299 oralig'ida bo'lsatrue.await javob.json()— javob tanasini o'qiydi va JSON sifatida tahlil qiladi. Natija — oddiy JavaScript obyekti.taom.nom,taom.narx— endi bu oddiy obyekt, obyektlar darsidagidek ishlatiladi.
Nega kod async funksiya ichida? Top-level await — funksiyadan tashqaridagi await — faqat modulda ishlaydi. Oddiy <script> faylida u SyntaxError beradi.
async funksiyaga o'ralgan kod esa hamma joyda ishlaydi: oddiy skriptda ham, modulda ham, Node'da ham. Shuning uchun bu darsda kodni async funksiyaga o'raymiz va oxirida chaqiramiz. Bu bloklarni saytda ham, kompyuteringizda node fayl.mjs bilan ham ishga tushirsa bo'ladi — natija bir xil.
4.3 Nega ikkita await?
Boshida g'alati tuyulishi tabiiy: so'rov bitta, await esa ikkita. Sababi — javob ikki bosqichda keladi:
- Avval status va sarlavhalar keladi. Shu lahzada birinchi Promise bajariladi — sizda
Responsebor, lekin tana hali to'liq yetib kelmagan bo'lishi mumkin. - Keyin tana keladi. Katta javob (rasm, uzun ro'yxat) bo'laklab, sekin keladi.
json()tananing hammasini oxirigacha o'qiydi va tahlil qiladi — bu ham vaqt oladi, shuning uchun u ham Promise qaytaradi.
Xuddi pochta kabi: avval eshik qo'ng'irog'i va qutining ustidagi yorliq (status, sarlavhalar). Qutini ochib, ichini olish (tana) — alohida qadam.
Sxemada qarang — kod, host (brauzer yoki Node) va server orasida nima bo'ladi:
sequenceDiagram
participant K as Kodingiz
participant H as Host
participant S as Server
K->>H: fetch(url)
H-->>K: Promise (kutilmoqda)
H->>S: GET /api/mashq/menyu/1
S-->>H: 200 + sarlavhalar
H-->>K: Response (1-await)
K->>H: javob.json()
S-->>H: tana: {"id":1,...}
H-->>K: obyekt (2-await)json() ichida aslida JSON asoslari darsidagi JSON.parse ishlaydi. 10-qismda "response.json() — ichida xuddi shu parse" degan edik — mana o'sha joy.
4.4 Event loop'da fetch
fetch event loop'ga qanday mos keladi? Xuddi taymer kabi: so'rov host'ning Web API qismida kutadi, javob kelgach esa Promise bajariladi va then callback'i microtask navbatiga tushadi (Event loop). Bu safar then zanjiri bilan yozamiz (Promise zanjiri) — har qadam navbatlarda ko'rinsin:
Asosiy xulosa: tarmoqni kutish paytida stek bo'sh. Sahifa bu orada bosishlarga javob beradi, animatsiyalar yuradi. 5 soniyalik so'rov ham sahifani qotirmaydi.
Tekshirib ko'ring:
const taom = javob.json();debawaitsiz yozilsa,taom.nomnima bo'ladi?
Javob
undefined. json() Promise qaytaradi, obyekt emas. Promise'da nom xususiyati yo'q. Avval await bilan kutish kerak: const taom = await javob.json();.
5. Response obyekti
5.1 Asosiy xususiyatlar
Response — fetch qaytaradigan javob obyekti. Bugun eng ko'p kerak bo'ladiganlari:
| Xususiyat | Nima | Misol |
|---|---|---|
status |
status kodi | 200, 404 |
ok |
status 200–299 bo'lsa true |
true |
statusText |
status matni | "OK" yoki "" |
headers |
javob sarlavhalari | headers.get("content-type") |
url |
javob qaysi manzildan keldi | "https://..." |
Sarlavhani nomi bilan olish — headers.get(nom). Nomning katta-kichik harfi ahamiyatsiz:
async function sarlavhaniKor() {
const javob = await fetch("https://ilmhamroh.uz/api/mashq/menyu");
console.log(javob.headers.get("Content-Type"));
console.log(javob.url);
}
sarlavhaniKor();Konsolda:
application/json; charset=utf-8
https://ilmhamroh.uz/api/mashq/menyuapplication/json — server tanani JSON deb aytyapti (MIME turlari). Headers obyektining boshqa imkoniyatlarini Request, Response, Headers darsida ko'ramiz.
statusText haqida bitta nozik joy. Node'da u "OK", "Not Found" kabi matn. Brauzerda esa ko'pincha bo'sh satr "": zamonaviy saytlar HTTP/2 da ishlaydi, unda status matni umuman yuborilmaydi. Shuning uchun dastur mantiqini statusText ga emas, status va ok ga quring.
5.2 Tanani o'qish usullari
Tanani qaysi ko'rinishda olishni o'zingiz tanlaysiz:
| Usul | Natija | Qachon |
|---|---|---|
json() |
obyekt yoki massiv | API javoblari (eng ko'p) |
text() |
satr | HTML, oddiy matn, CSV |
blob() |
Blob — fayl ko'rinishidagi baytlar |
rasm, PDF, yuklab olish |
Uchalasi ham Promise qaytaradi. text() ni sinab ko'ramiz — u tanani "xom" ko'rinishda beradi:
async function xomMatn() {
const javob = await fetch("https://ilmhamroh.uz/api/mashq/menyu/4");
const matn = await javob.text();
console.log(matn);
console.log(typeof matn);
}
xomMatn();Konsolda:
{"id":4,"nom":"Ko'k choy","narx":5000,"turkum":"ichimlik"}
stringBu — serverdan kelgan aynan o'sha matn. json() = text() + JSON.parse. blob() bilan rasm va fayllarni File va Blob darsida ishlatamiz. Yana arrayBuffer() va formData() usullari ham bor — ular kamroq kerak bo'ladi.
Diqqat: Tanani faqat bir marta o'qish mumkin.
json()dan keyintext()chaqirsangiz, xato chiqadi. Sababi va yechimi — "Ko'p uchraydigan xatolar" bo'limida.
6. Eng muhim tuzoq: 404 da fetch xato bermaydi
6.1 HTTP xatosi — bu ham javob
99-taomni so'raymiz. Ishga tushirishdan oldin o'ylab ko'ring: kod catch ga tushadimi?
async function taomniOl(id) {
try {
const javob = await fetch(
`https://ilmhamroh.uz/api/mashq/menyu/${id}`,
);
const taom = await javob.json();
console.log("Taom keldi:", taom);
} catch (xato) {
console.log("Xato ushlandi:", xato.message);
}
}
taomniOl(99);Konsolda:
Taom keldi: { xato: 'Taom topilmadi', id: 99 }catch ishlamadi! Kod "Taom keldi" deb yozdi, holbuki taom yo'q. Nega?
fetch uchun server javob berdimi — demak so'rov muvaffaqiyatli. 404 ham, 500 ham — server bergan to'liq javob: status, sarlavhalar, tana bilan. fetch Promise'ni shu javob bilan bajaradi. "Bu javob yaxshimi yoki yomonmi" — buni hal qilish sizning ishingiz.
URL'dagi ${id} — Template literals darsidagi usul. U yerda "fetch asoslari darsidan boshlab ko'p ishlaysiz" degan edik.
6.2 ok ni tekshiring
To'g'ri naqsh — har javobdan keyin ok ni tekshirish va yaxshi bo'lmasa, o'zingiz xato tashlash (throw va o'z xatolaringiz):
async function taomniOl(id) {
const javob = await fetch(
`https://ilmhamroh.uz/api/mashq/menyu/${id}`,
);
if (!javob.ok) {
throw new Error(`HTTP ${javob.status}`);
}
return javob.json();
}
async function korsat() {
try {
const osh = await taomniOl(1);
console.log("Taom:", osh.nom);
await taomniOl(99);
} catch (xato) {
console.log("Xato:", xato.message);
}
}
korsat();Konsolda:
Taom: Osh
Xato: HTTP 404Endi taomniOl faqat haqiqiy taomni qaytaradi; qolgan hamma holatda xato tashlaydi. Chaqiruvchi kod bitta try/catch bilan ikkalasini ham boshqaradi.
return javob.json() — await siz. async funksiya Promise qaytarsa, chaqiruvchining await i uni baribir kutadi. Bu yerda ikkalasi ham to'g'ri.
6.3 Server xato haqida nima dedi?
HTTP 404 — dasturchi uchun yetarli. Foydalanuvchiga esa "Taom topilmadi" deyish yaxshiroq. Mashq API'si xato javobining tanasida ham JSON beradi: {"xato": "..."}. Uni o'qib, xabarga qo'shamiz:
async function taomniOl(id) {
const url = `https://ilmhamroh.uz/api/mashq/menyu/${id}`;
const javob = await fetch(url);
const malumot = await javob.json();
if (!javob.ok) {
throw new Error(`${javob.status}: ${malumot.xato}`);
}
return malumot;
}
taomniOl(99).catch((xato) => console.log(xato.message));
taomniOl("abc").catch((xato) => console.log(xato.message));Natijalar parallel keladi, tartib tarmoqqa bog'liq bo'lishi mumkin. Shuning uchun "Konsolda:" o'rniga chiqishni so'z bilan aytamiz: 404: Taom topilmadi va 400: id butun son bo'lishi kerak. Birinchisi — bunday taom yo'q. Ikkinchisi — so'rovning o'zi noto'g'ri: id son bo'lishi kerak edi.
Diqqat: Hamma server xato javobida JSON qaytarmaydi. Ba'zan u HTML sahifa ("502 Bad Gateway") beradi — unda
json()o'zi xato tashlaydi. Real koddaokbo'lmaganda tanani ehtiyot bo'lib o'qing yoki faqat statusga tayaning. Bunday himoyalangan "API klient"ni API klient qatlami darsida yozamiz.
Tekshirib ko'ring:
https://ilmhamroh.uz/api/mashq/holat/500gafetchqilinsa,await fetch(...)qatori xato tashlaydimi?
Javob
Yo'q. Server javob berdi — status 500, tanasi {"holat":500,"xabar":"Serverda ichki xato"}. fetch Promise'ni shu Response bilan bajaradi, javob.ok esa false bo'ladi. Xatoni sezish — ok tekshiruvi orqali.
7. Tarmoq xatosi: fetch qachon rad etiladi
7.1 Javob umuman kelmasa
fetch faqat bitta holatda Promise'ni rad etadi: javob umuman olinmasa. Masalan:
- internet o'chiq;
- domen mavjud emas (DNS uni topa olmadi);
- server o'chirilgan, ulanib bo'lmaydi;
- brauzer xavfsizlik sababli so'rovni to'xtatdi (CORS, CSP — keyingi darslarda);
- so'rov bekor qilindi (
AbortController).
Mavjud bo'lmagan domenni sinaymiz. .example — hech kimga berilmaydigan, zaxiralangan domen:
async function sinab() {
try {
await fetch("https://nomalum.example/menyu");
} catch (xato) {
console.log(xato.name); // TypeError
console.log(xato.message); // fetch failed
console.log(xato.cause.code); // ENOTFOUND
}
}
sinab();Node xatoni TypeError: fetch failed deb ataydi. Haqiqiy sabab — cause xususiyatida (Stack trace va xato turlari darsidagi sabablar zanjiri). ENOTFOUND — "domen topilmadi". O'sha darsda server ishga tushirilmagan holatni ko'rgan edik — unda sabab ECONNREFUSED edi: "ulanish rad etildi, bu manzilda hech kim tinglamayapti".
Brauzerda esa xabar boshqacha: TypeError: Failed to fetch. Brauzer sababni kodga aytmaydi — u faqat DevTools konsolida ko'rinadi (masalan net::ERR_NAME_NOT_RESOLVED). Bu ataylab qilingan: begona sayt kodingiz orqali boshqa tarmoqlarni "paypaslab" ko'rmasin.
Bu blok node bayroqli — saytda «Ishga tushir» tugmasi yo'q. Brauzerda xato.message — Failed to fetch, xato.cause esa umuman bo'lmaydi.
7.2 Ikki xil xato — ikki xil ushlash
| HTTP xatosi | Tarmoq xatosi | |
|---|---|---|
| Misol | 404, 422, 500 | internet yo'q, domen yo'q |
| Server javob berdimi | ha | yo'q |
fetch Promise'i |
bajariladi | rad etiladi |
| Qanday sezasiz | javob.ok === false |
catch |
Ikkalasini ham bitta joyda boshqarish uchun — oldingi bo'limdagi naqsh: ok bo'lmasa o'zingiz throw qilasiz. Shunda ikkala yo'l ham bitta catch ga tushadi.
flowchart TD
F["await fetch(url)"] -->|"javob keldi"| O{"javob.ok?"}
F -->|"javob yo'q:<br/>tarmoq xatosi"| C["catch"]
O -->|"ha (2xx)"| J["await javob.json()"]
O -->|"yo'q (4xx, 5xx)"| T["throw new Error"]
T --> C
J --> M["ma'lumot bilan ishlash"]Sxemaga qarang: chap tarmoq (ok tekshiruvi) — sizning kodingiz. U bo'lmasa, 404 javobi to'g'ridan-to'g'ri "ma'lumot bilan ishlash"ga o'tib ketardi.
Maslahat: Tarmoq xatosini kompyuteringizda sinash oson. DevTools → Network paneli → No throttling ro'yxatidan Offline ni tanlang. Endi sahifadagi har bir
fetchrad etiladi. Keyin yana No throttling ga qaytaring.
8. Sahifada: yuklanmoqda, ma'lumot, xato
Endi hammasini brauzerda birlashtiramiz. Quyidagi natija oynasi ochilishi bilan menyuni so'raydi. Server javobini 1 soniya kechiktiramiz (?kechikish=1000) — "Yuklanmoqda..." holatini ko'rishingiz uchun:
<style>
body { font: 1rem/1.5 system-ui, sans-serif; margin: 1rem; }
ul { padding-left: 1.2rem; }
.xato { color: #b3261e; }
button { font: inherit; padding: 0.4rem 0.8rem; }
</style>
<h2>«Bahor» menyusi</h2>
<p id="holat" role="status">Yuklanmoqda...</p>
<ul id="royxat"></ul>
<button id="topilmagan" type="button">99-taomni so'rash</button>
<script>
const API = "https://ilmhamroh.uz/api/mashq";
const holat = document.getElementById("holat");
const royxat = document.getElementById("royxat");
async function olibKel(url) {
const javob = await fetch(url);
const malumot = await javob.json();
if (!javob.ok) throw new Error(malumot.xato);
return malumot;
}
async function menyuniYukla() {
try {
const menyu = await olibKel(`${API}/menyu?kechikish=1000`);
for (const taom of menyu) {
const li = document.createElement("li");
li.textContent = `${taom.nom} — ${taom.narx} so'm`;
royxat.append(li);
}
holat.textContent = `${menyu.length} ta taom`;
console.log("Menyu yuklandi:", menyu.length);
} catch (xato) {
holat.textContent = `Yuklab bo'lmadi: ${xato.message}`;
holat.className = "xato";
}
}
document.getElementById("topilmagan").addEventListener(
"click",
async () => {
try {
await olibKel(`${API}/menyu/99`);
} catch (xato) {
holat.textContent = `Xato: ${xato.message}`;
holat.className = "xato";
console.log("Ushlandi:", xato.message);
}
},
);
menyuniYukla();
</script>Konsolda:
Menyu yuklandi: 4Nimani ko'rdingiz:
- Avval "Yuklanmoqda...", bir soniyadan keyin to'rtta taom va "4 ta taom". Foydalanuvchi bo'sh sahifaga qarab "buzilgan" deb o'ylamaydi.
- «99-taomni so'rash» ni bosing — matn qizil "Xato: Taom topilmadi" ga aylanadi, konsolda
Ushlandi: Taom topilmadi. - «Qayta ishga tushirish» tugmasini bosib, kechikishni yana kuzating.
Shu sahifani Live Server'da ochsangiz, DevTools konsolida 404 dan keyin yana bitta qizil qator ko'rasiz: Failed to load resource: the server responded with a status of 404 (). Uni brauzerning o'zi yozadi — xatoni kodda ushlagan bo'lsangiz ham. Bu xabar "so'rov 404 bilan tugadi" degani, kodingiz buzildi degani emas.
Bu uch holat — yuklanmoqda, ma'lumot, xato — tarmoq bilan ishlaydigan har bir interfeysda bor. Ularni API klient qatlami darsida tartibli "holat" obyektiga yig'amiz.
Taom nomini textContent bilan yozdik, innerHTML bilan emas. Sababi — "Hujumchi nigohi" bo'limida.
Diqqat: Natija oynasida
fetchfaqathttps://ilmhamroh.uzga ishlaydi. Saytimizning xavfsizlik siyosati (CSP — Content Security Policy) boshqa domenlarga ulanishni bloklaydi:https://api.github.comkabi manzil natijadaFailed to fetchberadi. Bu sizning kodingiz xatosi emas. Boshqa API'larni o'z kompyuteringizda — Live Server yoki DevTools konsolida sinang. CSP'ni 13-qismda o'rganamiz.
8.1 DevTools'da so'rovni ko'ring
Chrome DevTools II darsida Network panelini ochgan edik va "Fetch/XHR filtri — JavaScript yuborgan so'rovlar, ularni fetch darsida o'zingiz yuborasiz" degan edik. Mana o'sha payt.
Live Server'da bo'sh sahifa oching, DevTools → Network → Fetch/XHR filtri.
Console ga yozing:
jsconst j = await fetch("https://ilmhamroh.uz/api/mashq/menyu"); console.log(await j.json());Network'da
menyuqatori paydo bo'ladi. Uni bosing: Headers — so'rov va javob sarlavhalari, Response — xom tana, Timing — qancha vaqt ketdi.
DevTools konsolida await ni funksiyasiz yozish mumkin — konsol buni maxsus qo'llab-quvvatlaydi.
9. Node'da fetch
fetch Node 18 dan beri global — hech narsa o'rnatish yoki import qilish shart emas. Node 24 da u barqaror (stable). Bu darsdagi js bloklar Node 24 da tekshirilgan.
Brauzer va Node fetch i deyarli bir xil ishlaydi, lekin uchta farqni biling:
- Node CORS va CSP tekshiruvlarini qilmaydi — bu brauzer qoidalari (CORS mijoz tomondan).
- Node'da nisbiy manzil (
fetch("/menyu")) ishlamaydi: "qaysi saytga nisbatan?" degan savolga javob yo'q. Faqat to'liq URL. - Xato xabarlari farq qiladi: Node —
fetch failed+cause, brauzer —Failed to fetch.
Shuning uchun bu kursda URL'ni doim to'liq yozamiz: https://ilmhamroh.uz/api/mashq/.... Kodingizni keyinroq GitHub Pages'ga ko'chirsangiz ham ishlayveradi.
10. Hujumchi nigohi
1. Server javobini HTML sifatida qo'yish. Taom nomi serverdan keladi. Agar kimdir bazaga taom nomini <img src=x onerror="..."> deb yozib qo'ysa-chi? Siz uni innerHTML ga qo'ysangiz, brauzer uni HTML deb o'qiydi va hujumchining skripti ishlaydi. Bu — XSS hujumi (innerHTML va XSS). Qarshi chora: serverdan kelgan matn — textContent bilan. Natijadagi kod shunday qilgan.
2. Maxfiy kalitni frontend kodga yozish. Ba'zi API'lar kalit (API key) talab qiladi. Uni brauzer kodiga fetch(url + "?key=...") deb yozsangiz, har bir foydalanuvchi DevTools → Network'da uni ko'radi va o'g'irlay oladi. Brauzerga ketgan hamma narsa — ochiq. Qarshi chora: maxfiy kalitli so'rovlarni o'z serveringiz orqali yuborish. Buni backend qismlarida qilamiz.
11. Ko'p uchraydigan xatolar
11.1 await ni unutish
const javob = fetch("https://ilmhamroh.uz/api/mashq/menyu/1");
console.log(javob.status); // undefinedjavob — Response emas, Promise. Promise'da status yo'q. Tuzatish: const javob = await fetch(...). json() uchun ham xuddi shunday — ikkala joyda await.
11.2 ok ni tekshirmaslik
Eng xavfli xato — chunki u jim. 404 javobining tanasi {xato: "..."} ekrani "taom" sifatida chiziladi: undefined — undefined so'm. Tuzatish: har fetch dan keyin if (!javob.ok) throw ....
11.3 HTML'ni json() bilan o'qish
Manzil xato bo'lsa, server ko'pincha JSON emas, HTML sahifa qaytaradi. Masalan, saytning bosh sahifasi:
async function sinab() {
const javob = await fetch("https://ilmhamroh.uz/");
console.log(javob.headers.get("content-type"));
try {
await javob.json();
} catch (xato) {
console.log(`${xato.name}: ${xato.message}`);
}
}
sinab();Konsolda:
text/html; charset=utf-8
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSONXatoni ataylab catch bilan ushlab, faqat xabarini chiqardik. Ushlanmasa, Node xato bilan birga butun HTML sahifani ham terminalga to'kib tashlaydi.
Tarjimasi: "Kutilmagan belgi <: <!DOCTYPE... — yaroqli JSON emas." Nega aynan <? JSON { yoki [ bilan boshlanishi kerak edi. HTML esa <!DOCTYPE html> bilan boshlanadi — tahlilchi birinchi belgidayoq to'xtadi. Brauzerda xabar oldiga Failed to execute 'json' on 'Response': qo'shiladi. Tuzatish: URL'ni tekshiring; DevTools → Network → Response tabida server aslida nima qaytarganini ko'ring.
11.4 Tanani ikki marta o'qish
async function sinab() {
const javob = await fetch("https://ilmhamroh.uz/api/mashq/menyu/1");
console.log(await javob.json());
console.log(await javob.text());
}
sinab();Node 24 da: TypeError: Body is unusable: Body has already been read. Chrome'da: TypeError: Failed to execute 'text' on 'Response': body stream already read. Ma'nosi bir xil: "tana allaqachon o'qilgan". Tana quvurdagi suvga o'xshaydi: bir marta oqib o'tadi, orqaga qaytmaydi. Nega aynan shunday ekanini Streams API darsida ko'ramiz. Tuzatish: bir marta o'qing va natijani o'zgaruvchida saqlang. Ikki marta kerak bo'lsa — javob.clone() (Request, Response, Headers).
11.5 Nisbiy yoki chala URL
async function sinab() {
await fetch("menyu");
}
sinab();Node 24 da: TypeError: Failed to parse URL from menyu — "menyu dan URL yasab bo'lmadi". Xabarda aynan siz bergan matn ko'rsatiladi — qaysi manzil buzuqligini shundan bilasiz. Brauzerda esa nisbiy manzil joriy sahifaga nisbatan ochiladi — va ko'pincha siz kutmagan joyga ketadi. Tuzatish: https:// bilan boshlanadigan to'liq manzil.
12. Mashqlar
1-mashq (oson): Mantining narxi
https://ilmhamroh.uz/api/mashq/menyu/3 dan taomni oling va konsolga Manti — 30000 so'm deb chiqaring. Ishora: async funksiya, ikkita await — biri fetch uchun, biri json() uchun.
Yechim
async function mantiniKorsat() {
const javob = await fetch("https://ilmhamroh.uz/api/mashq/menyu/3");
const taom = await javob.json();
console.log(`${taom.nom} — ${taom.narx} so'm`);
}
mantiniKorsat();Konsolda:
Manti — 30000 so'mBirinchi await — Response uchun, ikkinchisi — tanadagi obyekt uchun. taom — oddiy obyekt, uning xususiyatlari template literal ichida ishlatildi.
2-mashq (o'rta): Ichimliklar ro'yxati
?turkum=ichimlik so'rov parametri faqat ichimliklarni qaytaradi. turkumniOl(turkum) funksiyasini yozing: u massivni qaytarsin, ok bo'lmasa — Error tashlasin. Keyin turkumniOl("ichimlik") natijasidagi har taomni - Ko'k choy ko'rinishida chiqaring. Ishora: massivni for...of bilan aylaning.
Yechim
async function turkumniOl(turkum) {
const javob = await fetch(
`https://ilmhamroh.uz/api/mashq/menyu?turkum=${turkum}`,
);
if (!javob.ok) {
throw new Error(`HTTP ${javob.status}`);
}
return javob.json();
}
async function ichimliklarniKorsat() {
const ichimliklar = await turkumniOl("ichimlik");
for (const taom of ichimliklar) {
console.log(`- ${taom.nom}`);
}
console.log("Jami:", ichimliklar.length);
}
ichimliklarniKorsat();Konsolda:
- Ko'k choy
Jami: 1turkum URL ichiga qo'yildi. Bu yerda u oddiy so'z. Foydalanuvchi kiritgan matnni URL'ga qo'yishning xavfsiz yo'li — URLSearchParams — URL va URLSearchParams darsida.
3-mashq (qiyin): Sahifalab olish
Menyu sahifalarga bo'linib ham beriladi: ?sahifa=1&hajm=2 → { elementlar, sahifa, keyingi, jami }. keyingi — keyingi sahifa raqami yoki oxirgi sahifada null. hammasiniYigish() funksiyasini yozing: 1-sahifadan boshlab keyingi null bo'lguncha so'rasin va barcha taom nomlarini bitta massivga yig'sin. Har sahifa uchun 1-sahifa: 2 ta deb yozsin. Faylni kurs/mashqlar/11/17-fetch/sahifalar.mjs ga saqlang.
Ishora: let sahifa = 1; va while (sahifa !== null) sikli; har aylanishda sahifa = malumot.keyingi. Siklda await — so'rovlar ketma-ket boradi (Ketma-ket va parallel bajarish): keyingi sahifa raqamini faqat oldingi javobdan bilamiz.
Yechim
const API = "https://ilmhamroh.uz/api/mashq";
async function hammasiniYigish() {
const nomlar = [];
let sahifa = 1;
while (sahifa !== null) {
const javob = await fetch(`${API}/menyu?sahifa=${sahifa}&hajm=2`);
if (!javob.ok) throw new Error(`HTTP ${javob.status}`);
const malumot = await javob.json();
console.log(`${sahifa}-sahifa: ${malumot.elementlar.length} ta`);
for (const taom of malumot.elementlar) nomlar.push(taom.nom);
sahifa = malumot.keyingi;
}
return nomlar;
}
hammasiniYigish().then((nomlar) => console.log(nomlar.join(", ")));Konsolda:
1-sahifa: 2 ta
2-sahifa: 2 ta
Osh, Lag'mon, Manti, Ko'k choyBu yerda parallel so'rov (Promise.all) mumkin emas: 2-sahifa borligini faqat 1-sahifa javobidagi keyingi aytadi. Agar jami va hajm dan sahifalar sonini oldindan hisoblasangiz, qolganlarini parallel olsa bo'ladi. Real API'larda (GitHub, Telegram) sahifalash aynan shunday ishlaydi. Bunday siklni async generator'ga o'rashni Asinxron iteratsiya darsida ko'rgan edingiz.
git add 11/17-fetch/sahifalar.mjs
git commit -m "11/17: menyuni sahifalab yig'"13. Real ishda
- Har bir zamonaviy sayt. Instagram lentasi, Uzum'dagi mahsulotlar, Telegram Web'dagi xabarlar — sahifa ochilgandan keyin
fetch(yoki uning ustiga qurilgan kutubxona) bilan kelgan ma'lumot. DevTools → Network → Fetch/XHR filtrini istalgan saytda yoqib ko'ring. - Kutubxonalar. Ko'p loyihalarda
fetchto'g'ridan-to'g'ri emas, ustidagi qatlam orqali ishlatiladi: o'z "API klienti" (API klient qatlami) yoki Axios. React'da esa so'rov holatlarini TanStack Query kabi kutubxona boshqaradi — React 17-qismdan, hozir bilish shart emas. - Node'da. Server ham boshqa serverlarga
fetchqiladi: to'lov tizimi, Telegram Bot API, ob-havo xizmati. - Intervyu. "
fetch404 da reject qiladimi?" — junior intervyusining klassik savoli. Javob: yo'q, faqat tarmoq xatosida; HTTP xatosiniresponse.okbilan tekshirish kerak.
Xulosa
fetch(url)HTTP so'rov yuboradi va Promise qaytaradi; uResponsebilan bajariladi.- Tanani olish — alohida asinxron qadam:
await javob.json(),text(),blob(). Tana faqat bir marta o'qiladi. javob.status— kod,javob.ok— 2xx bo'lsatrue.statusTextga tayanmang.- 404 va 500 da
fetchrad etilmaydi —okni tekshirib, o'zingizthrowqiling. fetchfaqat javob umuman kelmasa rad etiladi: Node'dafetch failed(+cause), brauzerdaFailed to fetch.- «Bahor» mashq API'si —
https://ilmhamroh.uz/api/mashq: ochiq, deterministik, daqiqasiga 120 so'rov.
Keyingi dars: fetch bilan ma'lumot yuborish — bron formasini serverga jo'natamiz: POST, JSON, FormData va URLSearchParams, Content-Type qoidalari.
Manbalar
- MDN: "Using the Fetch API", "Response", "Window: fetch() method" — developer.mozilla.org
- WHATWG Fetch Standard — fetch.spec.whatwg.org
- Node.js hujjatlari: "Fetch" (globals) — nodejs.org/api/globals.html
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!