Mundarija (39)
- Bu darsda
- 1. Nega bu kerak?
- 2. Uchta obyekt
- 3. Headers — sarlavhalar to'plami
- 3.1 Yaratish va o'zgartirish
- 3.2 Qiymatlar cheklovi
- 3.3 Javob sarlavhalari: brauzer hammasini ko'rsatmaydi
- 4. Request — so'rov obyekti
- 4.1 Yasash va ishlatish
- 4.2 Tanali so'rov — bir martalik
- 5. Response — javob obyekti
- 5.1 Qo'shimcha xususiyatlar
- 5.2 Tanani o'qish usullari
- 5.3 clone() — tanani ikki marta o'qish
- 5.4 O'z javobingizni yasash
- 6. Opsiyalar — birma-bir
- 6.1 signal — bekor qilish va vaqt chegarasi
- 6.2 credentials — cookie yuborilsinmi
- 6.3 mode — origin qoidasi
- 6.4 cache — HTTP kesh bilan munosabat
- 6.5 redirect — yo'naltirishga ergashish
- 6.6 keepalive — sahifa yopilsa ham
- 6.7 priority — muhimlik darajasi
- 6.8 Qolganlari — bir gapda
- 7. Brauzer va Node farqlari
- 8. Hujumchi nigohi
- 9. Ko'p uchraydigan xatolar
- 9.1 Tanani clone() siz ikki marta o'qish
- 9.2 Ishlatilgan Request ni qayta yuborish
- 9.3 Brauzerda ruxsat berilmagan sarlavhani o'qish
- 9.4 Sarlavhada lotin bo'lmagan harf
- 9.5 TimeoutError ni xabar matni bilan tanish
- 10. Mashqlar
- 1-mashq (oson): Umumiy sarlavhalar
- 2-mashq (o'rta): Log yozadigan fetch
- 3-mashq (qiyin): Tarmoqsiz test
- 11. Real ishda
- Xulosa
- Manbalar
fetch Request, Response va Headers: so'rov opsiyalari, kesh, cookie va yo'naltirish
Qisqacha:
fetchichida uchta obyekt ishlaydi:Request(so'rov),Response(javob) va ikkalasidagiHeaders(sarlavhalar). Sozlamalar obyekti so'rovning xulqini boshqaradi:credentials— cookie yuborilsinmi,cache— HTTP keshdan foydalanilsinmi,redirect— yo'naltirishga ergashilsinmi,keepalive— sahifa yopilsa ham so'rov yetib borsinmi. Javob tanasini ikki marta o'qish kerak bo'lsa —response.clone().
Bu darsda
Headersobyektini yaratib,get,set,append,has,deletebilan boshqara olasiz.Requestobyektini yasab, uni qayta ishlatish qoidasini bilasiz.Responseningtype,redirected,bodyUsedxususiyatlarini vaclone()ni ishlata olasiz.credentials,mode,cache,redirect,keepalive,priority,signalopsiyalari nima qilishini tushuntira olasiz.- Brauzer va Node
fetchi qayerda farq qilishini bilasiz.
Oldin bilishingiz kerak: fetch asoslari, fetch bilan ma'lumot yuborish, HTTP sarlavhalari: MIME, cookie va kesh, Bekor qilish: AbortController.
1. Nega bu kerak?
Sardor «Bahor» sayti uchun fetch bilan ancha kod yozdi. Ishlayapti, lekin to'rtta savol paydo bo'ldi:
- Har so'rovga bir xil sarlavhalarni qo'lda yozyapti. Ularni bitta joyda saqlab, kerakli joyda biroz o'zgartirish mumkinmi?
- Xatoni tekshirish uchun javob matnini logga yozmoqchi — lekin keyin
json()"tana allaqachon o'qilgan" deydi. - Mehmon sahifani yopganda "sahifa yopildi" degan statistikani serverga yubormoqchi. So'rov yetib boradimi?
- Server so'rovni boshqa manzilga yo'naltirdi. Kod buni qanday sezadi?
To'rtalasining javobi fetch ning kamroq ko'rinadigan qismida. Oldingi ikki darsda method, headers, body ni ishlatdik. Bugun qolgan sozlamalarni va fetch ichidagi obyektlarni ochamiz.
2. Uchta obyekt
fetch(url, sozlamalar) chaqirganingizda ichkarida shunday bo'ladi:
flowchart LR
U["url +<br/>sozlamalar"] --> R["Request<br/>(so'rov)"]
R -- "fetch()" --> S[("Server")]
S --> P["Response<br/>(javob)"]
R -.- H1["Headers"]
P -.- H2["Headers"]Sxemaga qarang: manzil va sozlamalardan Request obyekti yasaladi, server javobidan esa Response obyekti. Ikkalasining ham sarlavhalari — alohida Headers obyekti. Bularni o'zingiz ham yasashingiz mumkin — new Headers(), new Request(), new Response(). Uchalasi brauzerda ham, Node'da ham global.
3. Headers — sarlavhalar to'plami
3.1 Yaratish va o'zgartirish
Headers — sarlavhalarni saqlaydigan obyekt. U oddiy obyektga o'xshaydi, lekin HTTP qoidalarini biladi:
const sarlavhalar = new Headers({ Accept: "application/json" });
sarlavhalar.set("Content-Type", "application/json");
sarlavhalar.append("X-Sinov", "bir");
sarlavhalar.append("X-Sinov", "ikki");
console.log(sarlavhalar.get("accept"));
console.log(sarlavhalar.has("ACCEPT"));
for (const [nom, qiymat] of sarlavhalar) {
console.log(nom, "=", qiymat);
}Konsolda:
application/json
true
accept = application/json
content-type = application/json
x-sinov = bir, ikkiUchta muhim xulq:
- Katta-kichik harf ahamiyatsiz.
Accept,accept,ACCEPT— bitta sarlavha. HTTP standarti shunday deydi. Ichkarida nomlar kichik harfda saqlanadi. setalmashtiradi,appendqo'shadi. Bir nomga ikki martaappend— qiymatlar vergul bilan birlashadi:bir, ikki.- Aylanish tartibi — alifbo bo'yicha.
for...ofsarlavhalarni nomi bo'yicha saralab beradi, qo'shilgan tartibda emas.
delete(nom) — sarlavhani o'chiradi. Headers ni fetch ga to'g'ridan-to'g'ri berish mumkin: fetch(url, { headers: sarlavhalar }). Oddiy obyekt ham ishlaydi — fetch uni o'zi Headers ga aylantiradi.
3.2 Qiymatlar cheklovi
Sarlavha nomi va qiymati — faqat lotin harflari va oddiy belgilar. Sababi tarixiy: HTTP sarlavhalari ISO-8859-1 (Latin-1) kodlashida yuboriladi. Kodlash (encoding) — har belgiga raqam beradigan jadval. Latin-1 jadvalida atigi 256 ta belgi bor, demak har belgining raqami 255 dan oshmaydi. O'zbekcha ʻ belgisi bilan sinaymiz:
const sarlavhalar = new Headers({ "X-Ism": "Gʻani" });Node 24 da:
TypeError: Cannot convert argument to a ByteString because the character at index 1 has a value of 699 which is greater than 255.Tarjimasi: "Argumentni bayt satriga aylantirib bo'lmadi: 1-o'rindagi belgining qiymati 699, bu 255 dan katta." ʻ belgisining raqami — 699. Chrome qisqaroq aytadi: String contains non ISO-8859-1 code point — "satrda ISO-8859-1 da yo'q belgi bor". Kursda nega oddiy apostrof ' ishlatishimizning yana bir sababi.
Ism, izoh kabi har qanday matnni sarlavhada emas, tanada yuboring. Sarlavhada albatta kerak bo'lsa — encodeURIComponent("Gʻani") bilan kodlang (URL va URLSearchParams).
Nom ichida bo'sh joy ("Ism Familiya") yoki qiymat ichida yangi qator ham xato beradi. Yangi qator bilan hujumchi so'rovga o'z sarlavhasini "ulab" yuborishi mumkin edi — Headers buni oldindan to'sadi.
3.3 Javob sarlavhalari: brauzer hammasini ko'rsatmaydi
Javobning ham headers i bor. Mashq API'si har javobga X-RateLimit-Limit (daqiqalik chegara) sarlavhasini qo'shadi. Node'da o'qiymiz:
async function chegarani() {
const url = "https://ilmhamroh.uz/api/mashq/menyu?sahifa=1&hajm=2";
const javob = await fetch(url);
console.log(javob.headers.get("X-Jami"));
console.log(javob.headers.get("X-RateLimit-Limit"));
}
chegarani();Konsolda:
4
120Endi xuddi shu kodni brauzerda — natija oynasida ishga tushiramiz. Qaysi sarlavhalarni ko'ramiz?
<p>Konsolga qarang.</p>
<script>
async function sarlavhalarniKor() {
const url =
"https://ilmhamroh.uz/api/mashq/menyu?sahifa=1&hajm=2";
const javob = await fetch(url);
console.log([...javob.headers.keys()].join(", "));
console.log("X-Jami:", javob.headers.get("X-Jami"));
console.log("Limit:", javob.headers.get("X-RateLimit-Limit"));
}
sarlavhalarniKor();
</script>Konsolda:
cache-control, content-length, content-type, x-jami, x-sorov-id
X-Jami: 4
Limit: nullBrauzerda X-RateLimit-Limit — null, garchi server uni yuborgan bo'lsa ham. DevTools → Network'da u ko'rinadi, lekin JavaScript'ga berilmaydi. Sabab — CORS: boshqa origin'dan kelgan javobning faqat "xavfsiz" sarlavhalari (Content-Type, Cache-Control, Content-Length ...) va server ruxsat bergan sarlavhalar (X-Jami, X-Sorov-Id) ochiladi. Ruxsat Access-Control-Expose-Headers sarlavhasida keladi. Batafsil — keyingi darsda, CORS mijoz tomondan.
Maslahat:
Set-Cookiesarlavhasi brauzerda JavaScript'ga umuman berilmaydi — cookie'ni brauzer o'zi boshqaradi. Node'da esa server bir nechta cookie yuborsa, ularni massiv qilib olish uchunheaders.getSetCookie()bor.
Tekshirib ko'ring:
h.set("X-A", "1"); h.append("x-a", "2"); h.get("X-A")nima qaytaradi?
Javob
"1, 2". X-A va x-a — bitta sarlavha (harf katta-kichikligi ahamiyatsiz). set qiymatni 1 qildi, append esa 2 ni vergul bilan qo'shdi.
4. Request — so'rov obyekti
4.1 Yasash va ishlatish
new Request(url, sozlamalar) — fetch ning argumentlari bilan aynan bir xil. Uni yasab, keyin fetch ga berasiz:
const sorov = new Request("https://ilmhamroh.uz/api/mashq/aks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ taom: "Osh" }),
});
console.log(sorov.method, sorov.url);
const { cache, credentials, mode, redirect } = sorov;
console.log(cache, credentials, mode, redirect);Konsolda:
POST https://ilmhamroh.uz/api/mashq/aks
default same-origin cors followIkkinchi qator — biz bermagan sozlamalarning standart qiymatlari. Ularni shu darsning "Opsiyalar" bo'limida birma-bir ko'ramiz.
Request qachon kerak? Asosan ikki joyda: so'rovni bir joyda yasab, boshqa joyda yuborish kerak bo'lganda (API klient qatlami) va Service Worker'da. Service Worker — sahifa bilan server orasida turadigan alohida skript; u sahifaning har bir so'rovini Request obyekti sifatida ushlaydi. Uni 13-qismda o'rganamiz (Service Worker), hozir bilish shart emas. Kundalik kodda fetch(url, sozlamalar) yetarli.
4.2 Tanali so'rov — bir martalik
Tanasi bor Request ni ikki marta yuborib bo'lmaydi. Tana quvurdagi suvga o'xshaydi: u birinchi fetch da "oqib ketadi":
async function ikkiMarta() {
const sorov = new Request("https://ilmhamroh.uz/api/mashq/aks", {
method: "POST",
body: "osh",
});
const birinchi = await fetch(sorov);
console.log(birinchi.status, sorov.bodyUsed);
try {
await fetch(sorov);
} catch (xato) {
console.log(xato.message);
}
}
ikkiMarta();Konsolda:
200 true
Cannot construct a Request with a Request object that has already been used.Tarjimasi: "Allaqachon ishlatilgan Request obyektidan yangi so'rov yasab bo'lmaydi." bodyUsed — true: tana ishlatildi. Yechim: yuborishdan oldin nusxa oling — fetch(sorov.clone()). Yoki eskisidan yangisini yasang: new Request(sorov, { method: "PUT" }) — hamma sozlama ko'chadi, faqat ko'rsatganingiz o'zgaradi.
5. Response — javob obyekti
5.1 Qo'shimcha xususiyatlar
fetch asoslari da status, ok, headers, url ni ko'rdik. Yana uchtasi:
| Xususiyat | Nima |
|---|---|
redirected |
javob yo'naltirishdan keyin keldimi (true/false) |
bodyUsed |
tana allaqachon o'qilganmi |
type |
javob turi: basic, cors, opaque ... |
type — brauzer javobni qanchalik "ochib" berganini aytadi. opaque so'zi inglizchada "xira, ichi ko'rinmaydigan" degani:
type |
Qachon | Nima o'qiladi |
|---|---|---|
basic |
o'z origin'ingizdan | hamma narsa (Set-Cookie dan tashqari) |
cors |
boshqa origin, CORS ruxsati bilan | tana va ruxsat berilgan sarlavhalar |
opaque |
mode: "no-cors" |
hech narsa: status 0, tana bo'sh |
opaqueredirect |
redirect: "manual" |
hech narsa, status 0 |
Natija oynasida mashq API'sidan kelgan javob — cors: u boshqa origin'dan, ruxsat bilan keldi. Node'da esa har doim basic — Node'da CORS yo'q.
5.2 Tanani o'qish usullari
| Usul | Natija |
|---|---|
json() |
obyekt / massiv |
text() |
satr |
blob() |
Blob (fayl ko'rinishidagi ma'lumot) |
arrayBuffer() |
xom baytlar xotirasi |
bytes() |
Uint8Array — baytlar massivi |
bytes() eng yangisi: 2025-yil yanvaridan beri hamma asosiy brauzerda (Baseline). Baytlar bilan File va Blob va Streams API darslarida ishlaymiz. Usul qaysi bo'lmasin — tana faqat bir marta o'qiladi.
5.3 clone() — tanani ikki marta o'qish
Sardorning ikkinchi savoli: javobni logga yozish va ishlatish. Yechim — clone(): javobning nusxasi, o'z tanasi bilan:
async function logBilan() {
const javob = await fetch("https://ilmhamroh.uz/api/mashq/menyu/2");
const nusxa = javob.clone();
console.log("Log:", await nusxa.text());
const taom = await javob.json();
console.log(taom.nom, taom.narx);
console.log(javob.bodyUsed, nusxa.bodyUsed);
}
logBilan();Konsolda:
Log: {"id":2,"nom":"Lag'mon","narx":28000,"turkum":"taom"}
Lag'mon 28000
true trueclone() ni tana o'qilishidan oldin chaqiring — keyin kech bo'ladi. Ikkala nusxa ham bir xil tanani alohida o'qiydi.
5.4 O'z javobingizni yasash
Response ni serversiz ham yasash mumkin. Bu testlar uchun juda qulay — "soxta server javobi":
async function soxtaJavob() {
const javob = Response.json({ nom: "Osh" }, { status: 201 });
console.log(javob.status, javob.ok);
console.log(javob.headers.get("content-type"));
console.log(await javob.json());
const topilmadi = new Response("Topilmadi", { status: 404 });
console.log(topilmadi.ok, await topilmadi.text());
}
soxtaJavob();Konsolda:
201 true
application/json
{ nom: 'Osh' }
false TopilmadiResponse.json(malumot, sozlamalar) — obyektni JSON qilib, Content-Type ni ham qo'yadi. U 2023-yildan beri hamma brauzerda bor. new Response(tana, sozlamalar) — istalgan tana bilan. 3-mashqda shu bilan fetch siz test yozasiz. Service Worker ham oflayn rejimda sahifaga aynan shunday yasalgan javob beradi.
Tekshirib ko'ring: Javobni
clone()qilmasdan avvaltext()bilan logga yozdingiz, keyinjson()chaqirdingiz. Nima bo'ladi?
Javob
json() xato tashlaydi: Node'da Body is unusable: Body has already been read, Chrome'da body stream already read. text() tanani allaqachon oxirigacha o'qib bo'lgan. Ikki marta kerak bo'lsa — o'qishdan oldin clone().
6. Opsiyalar — birma-bir
fetch ning ikkinchi argumentidagi sozlamalarni opsiyalar deymiz. method, headers, body ni bilasiz. Qolganlari:
6.1 signal — bekor qilish va vaqt chegarasi
AbortController darsida signal bilan asinxron ishni to'xtatishni o'rgandik. U fetch bilan ham ishlaydi — va aynan fetch uchun eng ko'p ishlatiladi. Server javobni 2 soniya kechiktiradi, biz esa 300 ms kutamiz:
async function vaqtChegarasi() {
const url = "https://ilmhamroh.uz/api/mashq/menyu?kechikish=2000";
try {
await fetch(url, { signal: AbortSignal.timeout(300) });
} catch (xato) {
console.log(xato.name);
}
}
vaqtChegarasi();Konsolda:
TimeoutErrorVaqt tugadi — fetch TimeoutError bilan rad etildi. Foydalanuvchi o'zi bekor qilsa (controller.abort()), xato nomi AbortError bo'ladi. Shu ikki nom bilan "vaqt tugadi" va "bekor qilindi" ni farqlaysiz. Xabar matni esa har xil: Node — The operation was aborted due to timeout, Chrome — signal timed out. Shuning uchun message ga emas, name ga tayaning.
6.2 credentials — cookie yuborilsinmi
Cookie — brauzer saytga avtomatik qo'shib yuboradigan kichik ma'lumot (masalan, "kim kirgan"). credentials buni boshqaradi:
| Qiymat | Cookie yuboriladi |
|---|---|
"same-origin" (standart) |
faqat o'z origin'ingizga |
"include" |
boshqa origin'ga ham |
"omit" |
hech qachon |
Odatda standart qiymat to'g'ri: o'z sayt API'ingizga cookie ketadi, begona saytga — yo'q. "include" frontend app.example.com da, API esa api.example.com da bo'lganda kerak. Lekin unda server ham alohida ruxsat berishi shart. Mashq API'si cookie ishlatmaydi va "include" bilan kelgan so'rovni brauzer bloklaydi — sababini va aniq xato matnini CORS mijoz tomondan darsida ko'ramiz.
6.3 mode — origin qoidasi
| Qiymat | Ma'nosi |
|---|---|
"cors" (standart) |
boshqa origin'ga ham, CORS qoidasi bilan |
"same-origin" |
faqat o'z origin'ingizga; boshqasiga — xato |
"no-cors" |
yuboradi, lekin javobni yashiradi (opaque) |
"no-cors" — CORS xatosini "tuzatish" emas: javob bo'sh keladi. Bu haqda Origin va Same-Origin Policy darsida ogohlantirgan edik; keyingi darsda haqiqiy natijasini ko'ramiz.
6.4 cache — HTTP kesh bilan munosabat
HTTP sarlavhalari darsida brauzer keshini ko'rgan edik: server Cache-Control bilan "buni 1 soat saqla" deydi va brauzer faylni qayta yuklamaydi. cache opsiyasi shu keshga fetch qanday munosabatda bo'lishini aytadi:
| Qiymat | Nima qiladi |
|---|---|
"default" |
HTTP qoidalari bo'yicha: yangi bo'lsa keshdan, eskirgan bo'lsa server bilan tekshiradi |
"no-store" |
keshga qaramaydi va javobni keshga yozmaydi |
"reload" |
keshga qaramaydi, lekin yangi javobni keshga yozadi |
"no-cache" |
keshdagini ishlatishdan oldin doim server bilan tekshiradi |
"force-cache" |
keshda bo'lsa — eskirgan bo'lsa ham — o'shani oladi |
Yana bitta — "only-if-cached": faqat keshdan, tarmoqqa umuman chiqmaydi. U faqat o'z origin'ingiz bilan ishlaydi; boshqa origin'ga Chrome 'only-if-cached' can be set only with 'same-origin' mode xatosini beradi.
Mashq API'si har javobga Cache-Control: no-store qo'yadi — server "hech qachon keshlama" deydi. Shuning uchun u bilan cache opsiyasining farqini ko'rmaysiz. O'z saytingizda DevTools → Network'dagi Size ustuniga qarang: keshdan kelgan javob (disk cache) yoki (memory cache) deb yoziladi.
6.5 redirect — yo'naltirishga ergashish
Server 301 yoki 302 bilan "bu narsa boshqa manzilda" deydi va Location sarlavhasida yangi manzilni beradi (HTTP status kodlari). Mashq API'sida /holat/301 aynan shunday: u /api/mashq/menyu ga yo'naltiradi.
| Qiymat | Nima qiladi |
|---|---|
"follow" (standart) |
yangi manzilga o'zi boradi |
"manual" |
ergashmaydi |
"error" |
yo'naltirish bo'lsa — tarmoq xatosi |
Standart holatda fetch yo'naltirishni sezdirmasdan bajaradi. Buni redirected va url dan bilasiz:
async function yonaltirish() {
const url = "https://ilmhamroh.uz/api/mashq/holat/301";
const javob = await fetch(url);
console.log(javob.status, javob.redirected);
console.log(javob.url);
}
yonaltirish();Konsolda:
200 true
https://ilmhamroh.uz/api/mashq/menyuBiz /holat/301 ni so'radik, javob esa /menyu dan keldi — status 200, redirected: true. Sardorning to'rtinchi savoliga javob shu.
"manual" da brauzer va Node farq qiladi. Brauzer javobni yashiradi: type: "opaqueredirect", status: 0 — yo'naltirish bo'lganini bilasiz, lekin qayerga ekanini emas. Node esa haqiqiy 301 ni va Location sarlavhasini beradi. "manual" brauzerda kamdan-kam kerak; Service Worker va serverdagi kodda ishlatiladi.
6.6 keepalive — sahifa yopilsa ham
Sardorning uchinchi savoli. Mehmon sahifani yopdi — pagehide hodisasi keldi (Sahifa hayot sikli). Shu paytda yuborilgan oddiy fetch ni brauzer sahifa bilan birga bekor qilishi mumkin. keepalive: true esa brauzerga aytadi: "sahifa yopilsa ham, bu so'rovni oxiriga yetkaz":
addEventListener("pagehide", () => {
fetch("https://ilmhamroh.uz/api/mashq/aks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ hodisa: "sahifa yopildi" }),
keepalive: true,
});
});Biz buni Chrome 154 da sinadik: sahifadan boshqa manzilga o'tilgandan keyin ham server so'rovni to'liq oldi. Undan oldin brauzer OPTIONS degan qo'shimcha tekshiruv so'rovini ham yubordi — uni keyingi darsda ko'ramiz. Bu so'rovning javobini hech kim o'qimaydi: sahifa allaqachon yo'q. keepalive — "yubor va unut" so'rovlari uchun.
Cheklovi: bir vaqtda yo'ldagi barcha keepalive so'rovlar tanasi jami 64 KB dan oshmasligi kerak. Oshsa, fetch darhol TypeError bilan rad etiladi. Shuning uchun u kichik statistika uchun, katta fayllar uchun emas.
Sahifa hayot sikli darsida "analitikani yuborish uchun fetch ning keepalive opsiyasi yoki navigator.sendBeacon bor" degan edik. Farqi: sendBeacon(url, tana) — faqat POST, sarlavhalarsiz va javobsiz, bitta qator. keepalive li fetch — istalgan metod va sarlavha bilan. keepalive 2024-yil noyabridan beri hamma asosiy brauzerda (Baseline).
6.7 priority — muhimlik darajasi
Sahifa bir vaqtda o'nlab so'rov yuboradi. priority brauzerga qaysi biri muhimroq ekanini aytadi: "high", "low" yoki "auto" (standart). Masalan, foydalanuvchi kutib turgan menyu — "high", orqa fondagi statistika — "low". Bu buyruq emas, maslahat: brauzer uni hisobga oladi, lekin tartibni kafolatlamaydi. 2024-yil oktabridan beri hamma asosiy brauzerda.
6.8 Qolganlari — bir gapda
referrer,referrerPolicy— so'rov qaysi sahifadan kelganini (Referersarlavhasi) qanchalik to'liq aytish.referrerPolicy: "no-referrer"— umuman aytmaslik.integrity— javob baytlarining "barmoq izi" (hash). Server boshqa narsa bersa,fetchrad etadi. Buni 13-qismda, Brauzer xavfsizlik modeli darsida (SRI) ko'ramiz.
Tekshirib ko'ring: Uch vaziyatga qaysi opsiya kerak? (a) Mehmon sahifani yopayotganda "sahifa yopildi" statistikasini yuborish. (b) Server 5 soniyada javob bermasa, kutishni to'xtatish. (c) Sayt
example.comda, APIapi.example.comda, so'rov bilan kirish cookie'si ham borishi kerak.
Javob
(a) keepalive: true — sahifa yopilsa ham so'rov yetib boradi. (b) signal: AbortSignal.timeout(5000) — 5 soniyadan keyin TimeoutError. (c) credentials: "include" — boshqa origin'ga ham cookie ketadi. Lekin buning uchun server ham alohida ruxsat berishi shart, buni keyingi darsda ko'ramiz.
7. Brauzer va Node farqlari
Opsiyalarning ko'pi brauzer tushunchalari: cookie qutisi, HTTP kesh, origin. Node'da ular yo'q. Node 24 bu opsiyalarni qabul qiladi, lekin ko'pini e'tiborsiz qoldiradi — mode: "no-cors" bilan ham u oddiy 200 javobni to'liq beradi:
| Brauzer | Node 24 | |
|---|---|---|
CORS, mode |
tekshiradi | yo'q |
credentials, cookie |
cookie qutisi bor | cookie avtomatik yuborilmaydi |
cache |
HTTP kesh bor | kesh yo'q |
| Javob sarlavhalari | CORS ruxsat berganlari | hammasi |
redirect: "manual" |
opaqueredirect, status 0 |
haqiqiy 301 + Location |
statusText |
HTTP/2 da "" |
"OK", "Not Found" ... |
Shuning uchun bu kursda tarmoq kodi ikki joyda tekshiriladi: ```js bloklar — Node 24 da, brauzerga xos xulq — natija oynasida, haqiqiy Chrome'da.
8. Hujumchi nigohi
1. credentials: "include" ni hamma joyga qo'yish. "Cookie kerak bo'lib qolar" deb Sardor uni barcha so'rovlarga yozdi — begona domenlarga ham. Endi foydalanuvchining cookie'lari (kirish sessiyasi bilan) o'sha serverlarga ham ketadi, ular esa uni o'z loglariga yozishi mumkin. Qarshi chora: include — faqat o'zingizning va ishonchli API'ingizga, aniq kerak bo'lganda.
2. Sarlavhaga foydalanuvchi matnini qo'yish. Agar sarlavhalar qo'lda satr bilan yig'ilsa, foydalanuvchi kiritgan \r\n yangi sarlavha "ulab" yuborishi mumkin edi (header injection). Headers buni invalid header value xatosi bilan to'sadi — shuning uchun sarlavhalarni doim Headers yoki headers obyekti orqali bering. Foydalanuvchi matni esa umuman tanada bo'lgani yaxshi.
9. Ko'p uchraydigan xatolar
9.1 Tanani clone() siz ikki marta o'qish
text() dan keyin json() — xato. Tuzatish: o'qishdan oldin const nusxa = javob.clone().
9.2 Ishlatilgan Request ni qayta yuborish
Cannot construct a Request with a Request object that has already been used. Tuzatish: fetch(sorov.clone()) yoki har safar yangi Request.
9.3 Brauzerda ruxsat berilmagan sarlavhani o'qish
Node'da X-RateLimit-Limit bor, brauzerda — null. Kod "server buzildi" deb o'ylaydi. Tuzatish: kerakli sarlavhani server Access-Control-Expose-Headers ga qo'shishi kerak (CORS mijoz tomondan).
9.4 Sarlavhada lotin bo'lmagan harf
Gʻani, Ғани — TypeError. Tuzatish: matnni tanada yuboring yoki encodeURIComponent bilan kodlang.
9.5 TimeoutError ni xabar matni bilan tanish
xato.message === "signal timed out" — faqat Chrome'da ishlaydi. Tuzatish: xato.name === "TimeoutError".
10. Mashqlar
1-mashq (oson): Umumiy sarlavhalar
Headers obyekti yasang: Accept: application/json va X-Sinov: bahor. Unga X-Sinov ni qish qiymati bilan append qiling va aks ga GET bilan yuboring. Javobdagi sarlavhalar["x-sinov"] ni chiqaring. Ishora: aks X-Sinov sarlavhasini qaytarib beradi.
Yechim
async function sinovSarlavhasi() {
const sarlavhalar = new Headers({
Accept: "application/json",
"X-Sinov": "bahor",
});
sarlavhalar.append("X-Sinov", "qish");
const javob = await fetch("https://ilmhamroh.uz/api/mashq/aks", {
headers: sarlavhalar,
});
const aks = await javob.json();
console.log(aks.sarlavhalar["x-sinov"]);
}
sinovSarlavhasi();Konsolda:
bahor, qishappend ikkinchi qiymatni vergul bilan qo'shdi va server bitta sarlavha sifatida oldi. set ishlatsangiz — faqat qish qolardi.
2-mashq (o'rta): Log yozadigan fetch
logliFetch(url) funksiyasini yozing: u javob statusini va tananing birinchi 30 belgisini [log] 200 {"id":3,... ko'rinishida chiqarsin, keyin tanani JSON qilib qaytarsin. Tana bir marta o'qilishini unutmang. /menyu/3 bilan sinang. Ishora: clone() va satrning slice(0, 30) metodi (Kesish, birlashtirish — massivdagidek, satrda ham bor).
Yechim
async function logliFetch(url) {
const javob = await fetch(url);
const matn = await javob.clone().text();
console.log(`[log] ${javob.status} ${matn.slice(0, 30)}`);
return javob.json();
}
async function sina() {
const url = "https://ilmhamroh.uz/api/mashq/menyu/3";
const taom = await logliFetch(url);
console.log(taom.nom);
}
sina();Konsolda:
[log] 200 {"id":3,"nom":"Manti","narx":3
Mantijavob.clone().text() — nusxaning tanasi o'qildi, asl javobniki esa butun qoldi. Real loyihalarda bunday "log qatlami" API klientga qo'yiladi (API klient qatlami).
3-mashq (qiyin): Tarmoqsiz test
fetch asoslari dagi taomniOl(id) ni o'zgartiring: u fetch funksiyasini ikkinchi parametr sifatida olsin — taomniOl(id, olibKel = fetch). Keyin soxtaFetch yozing: u tarmoqqa chiqmasdan, id 1 bo'lsa Response.json({ id: 1, nom: "Osh" }), aks holda 404 li javob qaytarsin. taomniOl ni ikkala holatda tekshiring. Faylni kurs/mashqlar/11/19-soxta-javob/test.mjs ga saqlang.
Ishora: soxtaFetch — async funksiya, URL oxiridagi raqamni url.endsWith("/1") bilan tekshiring. Response.json ikkinchi argumentida status beriladi.
Yechim
async function taomniOl(id, olibKel = fetch) {
const url = `https://ilmhamroh.uz/api/mashq/menyu/${id}`;
const javob = await olibKel(url);
if (!javob.ok) throw new Error(`HTTP ${javob.status}`);
return javob.json();
}
async function soxtaFetch(url) {
if (url.endsWith("/1")) return Response.json({ id: 1, nom: "Osh" });
return Response.json({ xato: "Taom topilmadi" }, { status: 404 });
}
async function testlar() {
const osh = await taomniOl(1, soxtaFetch);
console.log("1-test:", osh.nom === "Osh" ? "o'tdi" : "yiqildi");
try {
await taomniOl(99, soxtaFetch);
console.log("2-test: yiqildi");
} catch (xato) {
const otdi = xato.message === "HTTP 404";
console.log("2-test:", otdi ? "o'tdi" : "yiqildi");
}
}
testlar();Konsolda:
1-test: o'tdi
2-test: o'tdiIkkala test ham tarmoqsiz o'tdi — internet bo'lmasa ham, server o'chiq bo'lsa ham. olibKel = fetch — standart qiymat: oddiy ishlatishda haqiqiy fetch, testda — soxtasi. Bu usul bog'liqlikni tashqaridan berish (dependency injection) deyiladi. Testlarni node:test bilan 12-qismda tartibli yozamiz.
git add 11/19-soxta-javob/test.mjs
git commit -m "11/19: taomniOl ni tarmoqsiz sina"11. Real ishda
- API klientlar. Axios, ky kabi kutubxonalar va o'z "API klient"ingiz — umumiy
Headers,signalbilan vaqt chegarasi,clone()bilan log. Bularni API klient qatlami darsida bitta modulga yig'amiz. - Analitika. Google Analytics, Plausible kabi xizmatlar sahifa yopilganda ma'lumotni
keepaliveyokisendBeaconbilan yuboradi. - Service Worker va PWA. Oflayn rejimda sahifaning
Requestlarini ushlab, keshdan yokinew Response(...)bilan javob berish — Service Worker darsida. - Testlar.
Response.jsonbilan soxta javob — frontend testlarining kundalik usuli. React qismlarida MSW kabi kutubxonalar aynan shuRequest/Responseobyektlari ustiga qurilgan; hozir bilish shart emas.
Xulosa
fetchichida uch obyekt:Request,Responseva ikkalasidagiHeaders. Uchalasini o'zingiz ham yasay olasiz.Headers: nomlar harf katta-kichikligiga sezgir emas;setalmashtiradi,appendqo'shadi; qiymat — faqat Latin-1.- Tana bir marta o'qiladi: ikki marta kerak bo'lsa —
clone(). TanaliRequestham bir martalik. credentials— cookie,mode— origin qoidasi,cache— HTTP kesh,redirect— yo'naltirish,keepalive— sahifa yopilsa ham,priority— muhimlik,signal— bekor qilish.- Brauzer boshqa origin javobining faqat ruxsat berilgan sarlavhalarini ko'rsatadi; Node — hammasini.
- Ko'p opsiyalar brauzer tushunchasi: Node ularni qabul qiladi, lekin e'tiborsiz qoldiradi.
Keyingi dars: CORS mijoz tomondan — brauzer nega ba'zi javoblarni yashiradi: origin, preflight so'rovi, credentials: "include" va CORS xatosini o'qish.
Manbalar
- MDN: "Headers", "Request", "Response", "RequestInit" (fetch() options) — developer.mozilla.org
- WHATWG Fetch Standard: "Request class", "Response class", "keepalive" — fetch.spec.whatwg.org
- web-features (Baseline):
fetch-priority(2024-10),keepalive(2024-11),Response.bytes(2025-01),Response.json(2023-09)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!