2.11-bob: Asinxron JS — callback, Promise, async/await, fetch
2-QISM — JavaScript (0 dan chuqurgacha) · 11-mavzu
1. Kirish va motivatsiya
Bu — JavaScript'ning eng muhim va eng ko'p so'raladigan mavzularidan biri. Hozirgacha kod bir zumda ishladi. Lekin real dunyoda ko'p ish vaqt oladi: tarmoqdan ma'lumot olish 0.4-bob, fayl o'qish 0.2-bob, ma'lumotlar bazasiga so'rov (6), taymer. Bularni kutib turish kerak — lekin JS bir thread'li (0.1, 0.5: bitta oshpaz)! Agar kutsa, butun sahifa qotib qoladi.
Asinxron JS aynan shu muammoni hal qiladi: ish "fonda" bajarilsin, JS esa boshqa ishni davom ettirsin, ish tugaganda natija kelsin. 0.5-bobda ko'rgan event loop — buning mexanizmi.
O'xshatish: restoran ofitsianti (JS thread). U buyurtmani oshxonaga beradi (asinxron ish), lekin oshxona pishirguncha turib kutmaydi — boshqa stollarga xizmat qiladi. Taom tayyor bo'lganda (natija), uni olib keladi. Agar ofitsiant har taom oldida turib kutsa — restoran qotib qolardi. Asinxron JS — aynan shu.
Promise, async/await, fetchsiz zamonaviy JS yo'q. Har bir API so'rovi (5, 11.5, 12), DB amali (6), fayl ishi 5.3-bob — asinxron. Bu bobni mukammal bilish — majburiy.
2. Nazariya — chuqur tushuntirish
2.1. Sinxron vs asinxron
- Sinxron (synchronous): kod qatorma-qator, har biri oldingisini kutadi (bloklaydi).
- Asinxron (asynchronous): uzoq ish "fonga" topshiriladi; JS kutmasdan davom etadi; natija keyin keladi.
console.log("1");
setTimeout(() => console.log("2"), 1000); // 1 sek keyin (asinxron)
console.log("3");
// Natija: 1, 3, 2 "2" kutmasdan "3" chiqdi (event loop — 0.5)Bu — 0.5-bobdagi event loop'ning amaliy ko'rinishi: setTimeout brauzer/Node'ga topshiriladi, JS davom etadi, vaqt tugagach callback navbatga (queue) qo'yiladi.
2.2. Callback va "callback hell"
Eng eski asinxron usul — callback: "ish tugagach, shu funksiyani chaqir":
// Callback — natija tayyor bo'lganda chaqiriladigan funksiya (2.3)
setTimeout(() => {
console.log("1 sekund o'tdi");
}, 1000);Lekin ketma-ket asinxron ishlar "callback hell" (do'zaxi) ga olib keladi — chuqur, o'qishsiz ichma-ich:
// CALLBACK HELL — "qiyshiq piramida"
userOl(id, (user) => {
buyurtmaOl(user, (buyurtma) => {
tafsilotOl(buyurtma, (tafsilot) => {
tolovOl(tafsilot, (tolov) => {
console.log(tolov); // 4 daraja ichga — o'qishsiz, xatoni ushlash qiyin
});
});
});
});Bu muammoni Promise hal qildi.
2.3. Promise — asinxron natija "va'dasi"
Promise — kelajakda tayyor bo'ladigan natija "va'dasi". U uch holatda bo'ladi:
pending (kutilmoqda)
│
├──▶ fulfilled (bajarildi) — natija bor (.then)
└──▶ rejected (rad etildi) — xato bor (.catch)const promise = new Promise((resolve, reject) => {
// resolve — muvaffaqiyat; reject — xato
setTimeout(() => {
const ok = true;
if (ok) resolve("Natija!"); // fulfilled
else reject(new Error("Xato")); // rejected
}, 1000);
});
promise
.then(natija => console.log(natija)) // fulfilled bo'lsa (2.3: callback)
.catch(xato => console.error(xato)) // rejected bo'lsa
.finally(() => console.log("Tugadi")); // har holda2.4. .then zanjiri — callback hell yechimi
Promise'lar zanjirlanadi (har .then yangi Promise qaytaradi) — "piramida" tekislanadi:
// .then zanjiri (2.2-dagi callback hell o'rniga)
userOl(id)
.then(user => buyurtmaOl(user)) // har qadam keyingisini qaytaradi
.then(buyurtma => tafsilotOl(buyurtma))
.then(tafsilot => console.log(tafsilot))
.catch(xato => console.error(xato)); // BITTA catch — barcha xatolargaBu — callback hell'dan ancha o'qishli. Lekin async/await yana ham yaxshi.
2.5. async/await — eng zamonaviy, eng o'qishli
async/await — Promise'ni sinxron kabi yozish (lekin asinxron ishlaydi). Eng yaxshi usul:
asyncfunksiya — doim Promise qaytaradi.await— Promise tayyor bo'lishini kutadi (faqatasyncichida), natijani qaytaradi.
// async/await — eng o'qishli (2.4-dagi zanjir o'rniga)
async function malumotOl(id) {
try {
const user = await userOl(id); // kutadi, natija oladi
const buyurtma = await buyurtmaOl(user); // ketma-ket, lekin tekis
const tafsilot = await tafsilotOl(buyurtma);
return tafsilot;
} catch (xato) { // xatoni try/catch bilan (2.12)
console.error(xato);
}
}
awaitqanday ishlaydi 0.5-bob:awaitfunksiyani pauza qiladi va davomini microtask sifatida rejalashtiradi; thread bloklanmaydi — boshqa kod ishlayveradi. Funksiyaasyncbo'lishi shart.
2.6. async funksiya — doim Promise
async function f() { return 42; }
f(); // Promise<42> (son emas, Promise!)
f().then(v => console.log(v)); // 42
// yoki: const v = await f(); (boshqa async ichida)
// throw — rejected Promise (2.12)
async function g() { throw new Error("xato"); }
g().catch(e => console.log(e.message)); // "xato"2.7. fetch — tarmoq so'rovi (0.4 amalda)
fetch — HTTP so'rov yuborish 0.4-bob; u Promise qaytaradi:
async function userOl(id) {
const res = await fetch(`https://api.example.com/users/${id}`); // 0.4
if (!res.ok) { // status tekshiruvi (0.4: fetch 404'da ham "ok" emas)
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json(); // body'ni JSON'ga 2.8-bob — bu ham Promise!
return data;
}Ikki
await:fetchjavobi (response) keladi, keyin.json()body'ni o'qiydi — ikkalasi ham asinxron. Vares.okni tekshirish shart (0.4:fetch404/500'da rad etmaydi).
2.8. Promise kombinatorlari — parallel ishlar
Bir nechta asinxron ishni parallel bajarish (ketma-ket emas — tezroq):
// Promise.all — HAMMASI tayyor bo'lsin (biri xato bo'lsa — butun rad — MDN)
const [user, postlar, izohlar] = await Promise.all([
userOl(id), postlarOl(id), izohlarOl(id),
]); // uchchalasi PARALLEL — eng tez
// Promise.allSettled — hammasini kut, har birining natijasini ber (xato bo'lsa ham — MDN)
const natijalar = await Promise.allSettled([a(), b(), c()]);
// [{status:"fulfilled", value}, {status:"rejected", reason}, ...]
// Promise.race — BIRINCHi tugagani — masalan timeout
const natija = await Promise.race([sorov(), timeout(5000)]);
// Promise.any — birinchi MUVAFFAQIYATLI| Kombinator | Qachon tugaydi | Xato bo'lsa |
|---|---|---|
Promise.all |
hammasi fulfilled | birinchi xato — butun rad |
Promise.allSettled |
hammasi settled | har biri natija (rad ham) |
Promise.race |
birinchi settled (ok yoki xato) | birinchi xato bo'lsa rad |
Promise.any |
birinchi fulfilled | hammasi rad bo'lsagina rad |
Muhim: ketma-ket
await(biri-birini kutadi) — sekin; mustaqil ishlar bo'lsaPromise.allbilan parallel — ancha tez.
2.9. Event loop va microtask (0.5 chuqurroq)
Promise callback'lari (.then/await) — microtask navbatiga tushadi; setTimeout — macrotaskga. Microtasklar har doim oldin ishlaydi:
console.log("1"); // sinxron
setTimeout(() => console.log("2"), 0); // macrotask
Promise.resolve().then(() => console.log("3")); // microtask
console.log("4"); // sinxron
// Natija: 1, 4, 3, 2
// sinxron (1,4) microtask (3) macrotask (2)(Bu — 5.1-bobda Node event loop'da yana chuqurroq ochiladi.)
2.10. Top-level await — asyncsiz await
Odatda await faqat async funksiya ichida ishlaydi 2.5-bob. Lekin ES modul (type: "module" yoki .mjs) eng yuqori darajada (funksiyasiz) ham await ishlatishga ruxsat beradi — bu top-level await:
// ES modul ichida — eng yuqori darajada, async funksiyasiz
const res = await fetch("https://api.example.com/data"); // 0.4
const data = await res.json();
console.log(data);
// Oddiy <script> yoki CommonJS'da — SyntaxError (modul emas)Diqqat: top-level
awaitmodul yuklanishini to'xtatib turadi — bu modulga bog'liq boshqa modullar ham kutadi. Shuning uchun og'ir/sekin ishlarda ehtiyot bo'ling. Sozlash yoki bir martalik dastlabki ma'lumotni olishda qulay; lekin oddiy funksiya ichida baribirasynckerak 2.5-bob.
3. Sintaksis — tez ma'lumotnoma
// Promise
new Promise((resolve, reject) => {});
p.then(v => {}).catch(e => {}).finally(() => {});
// async/await
async function f() {
try {
const x = await promise;
return x;
} catch (e) {}
}
// fetch (0.4)
const res = await fetch(url);
if (!res.ok) throw new Error(res.status);
const data = await res.json();
// parallel
await Promise.all([a(), b()]); // hammasi
await Promise.allSettled([a(), b()]); // har biri natija
await Promise.race([a(), timeout()]); // birinchi4. Batafsil kod namunalari
Misol 1 — Promise yaratish va ishlatish (2.3)
function kechikish(ms) {
return new Promise(resolve => setTimeout(resolve, ms)); // ms dan keyin resolve
}
// .then bilan
kechikish(1000).then(() => console.log("1 sek o'tdi"));
// async/await bilan 2.5-bob — o'qishliroq
async function ishla() {
console.log("Boshlandi");
await kechikish(1000); // 1 sek kutadi (bloklamasdan)
console.log("1 sek o'tdi");
}Misol 2 — fetch va xatoni boshqarish (2.7, 2.12)
async function userOl(id) {
try {
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`); // 0.4 — tekshir!
const user = await res.json(); // 2.8
return user;
} catch (xato) {
console.error("Xato:", xato.message); // tarmoq yoki HTTP xatosi (2.12)
return null; // yoki qayta throw
}
}
const user = await userOl(1);
console.log(user?.name); // ?. — null bo'lsa qulamaydi (2.1)Misol 3 — Ketma-ket vs parallel (2.8)
// KETMA-KET — sekin (har biri oldingini kutadi: 3 sek)
async function sekin() {
const a = await sorov1(); // 1 sek
const b = await sorov2(); // 1 sek
const c = await sorov3(); // 1 sek
return [a, b, c]; // jami ~3 sek
}
// PARALLEL — tez (uchchalasi birga: ~1 sek)
async function tez() {
const [a, b, c] = await Promise.all([sorov1(), sorov2(), sorov3()]);
return [a, b, c]; // jami ~1 sek (mustaqil bo'lsa)
}Misol 4 — Timeout bilan race va allSettled (2.8)
// So'rovga vaqt chegarasi (race — 2.8)
function timeout(ms) {
return new Promise((_, reject) =>
setTimeout(() => reject(new Error("Vaqt tugadi")), ms)
);
}
async function vaqtBilan(url) {
return Promise.race([fetch(url), timeout(5000)]); // 5 sek dan oshsa — xato
}
// Bir nechta so'rov — ba'zisi xato bo'lsa ham davom (allSettled — 2.8)
async function hammasiniOl(idlar) {
const natijalar = await Promise.allSettled(idlar.map(id => userOl(id)));
const muvaffaq = natijalar
.filter(r => r.status === "fulfilled") // faqat muvaffaqiyatli (2.7)
.map(r => r.value);
return muvaffaq;
}5. To'g'ri va noto'g'ri holatlar
1) awaitni asyncsiz ishlatish
// SyntaxError — await faqat async ichida (2.5)
function f() { const x = await p(); }
//
async function f() { const x = await p(); }2) awaitni unutish
// Promise obyektini oladi (natija emas!)
async function f() { const data = userOl(1); console.log(data.name); }
// data — Promise, data.name — undefined
// await bilan
const data = await userOl(1);3) Ketma-ket await (mustaqil ishlar uchun)
// mustaqil so'rovlar ketma-ket — sekin (2.8)
const a = await x(); const b = await y();
// parallel
const [a, b] = await Promise.all([x(), y()]);4) fetchda res.okni tekshirmaslik
// 404/500'da ham "muvaffaqiyat" deb davom etadi (0.4)
const res = await fetch(url);
const data = await res.json(); // xato javobni "ma'lumot" deb oladi
// tekshir
if (!res.ok) throw new Error(res.status);6. Keng tarqalgan xatolar va yechimlari
Xato 1 — await is only valid in async functions
Sababi: await asyncsiz funksiyada 2.5-bob. Yechimi: funksiyani async qiling (yoki top-level await — ES modulda).
Xato 2 — Cannot read properties of undefined (Promise natijasida)
Sababi: await unutildi — Promise obyektiga murojaat (5-bo'lim). Yechimi: await qo'shing; ?. bilan himoyalaning 2.1-bob.
Xato 3 — UnhandledPromiseRejection
UnhandledPromiseRejection: ...Sababi: Promise rad etildi, lekin .catch/try-catch yo'q 2.3-bob. Yechimi: har asinxron ishni try/catch (async) yoki .catch bilan o'rang 2.12-bob.
Xato 4 — fetch tarmoq xatosi vs HTTP xatosi
Sababi: fetch faqat tarmoq uzilsa rad etadi; 404/500 — rad etmaydi 0.4-bob. Yechimi: res.okni alohida tekshiring 2.7-bob.
Xato 5 — Tsiklda await (sekinlik)
// har iteratsiya kutadi — sekin
for (const id of idlar) { await userOl(id); }
// parallel
await Promise.all(idlar.map(id => userOl(id)));Sababi: ketma-ket kutish 2.8-bob. Yechimi: Promise.all + map 2.7-bob.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Event loop (0.5, 5.1): asinxronlikning mexanizmi; microtask/macrotask.
- fetch/Axios (2.17, 2.18): API so'rovlari — Promise.
- Error handling 2.12-bob:
try/catchasync bilan. - React 11.5-bob:
useEffectda ma'lumot olish (async); 12 — TanStack Query/RTK Query (asinxron holatni boshqaradi). - Node/Express (5): so'rovlarni asinxron qayta ishlash; DB (6) — async.
- DB (6): har query — Promise (
await db.query(...)). - Streams 5.4-bob: katta ma'lumotni asinxron oqimda.
8. Eng yaxshi amaliyotlar (best practices)
async/awaitishlating (.thenzanjiri o'rniga) — o'qishliroq 2.5-bob.- Har asinxron ishni
try/catchbilan o'rang 2.12-bob;fetchdares.oktekshiring 2.7-bob. - Mustaqil ishlar —
Promise.all(parallel, tez); tsikldaawaito'rnigaPromise.all + map2.8-bob. awaitni unutmang — natija Promise emas, qiymat bo'lsin (5-bo'lim).Promise.allSettled— ba'zisi xato bo'lsa ham davom etish kerak bo'lganda 2.8-bob.- Timeout uchun
Promise.race(2.8, Misol 4). UnhandledPromiseRejectiondan qoching — har Promise'ning.catch/try-catch'i bo'lsin.- Asinxron funksiya doim Promise qaytaradi — buni esda tuting 2.6-bob.
9. Amaliy loyiha: "Ob-havo va Ma'lumot Yig'uvchi (Async)"
Asinxron JS'ni real API bilan amalda mustahkamlovchi loyiha.
Maqsad
fetch, async/await, try/catch va Promise kombinatorlarini ishlatib, bir nechta manbadan ma'lumot oluvchi, xatoga chidamli dastur yozish.
Talablar (requirements)
malumotOl(url):fetch+res.oktekshiruvi +res.json()+try/catch(Misol 2). Ochiq API ishlating (masalanjsonplaceholder.typicode.com).- Ketma-ket zanjir: foydalanuvchi uning postlari birinchi postning izohlari (
async/await, har biri oldingiga bog'liq). - Parallel (
Promise.all): bir nechta foydalanuvchini bir vaqtda oling; ketma-ket va parallel vaqtini solishtiring (console.time— 0.5) (Misol 3). - Chidamli (
Promise.allSettled): bir nechta so'rovdan ba'zisi xato (noto'g'ri URL) bo'lsa ham, muvaffaqiyatlilarini qaytaring (Misol 4). - Timeout (
Promise.race): so'rovga 5 sekund chegara; oshsa — "Vaqt tugadi" (Misol 4). - Xatoni to'g'ri boshqarish: tarmoq xatosi, HTTP xatosi (404) va timeout — uch holatni alohida xabar bilan (2.12, 0.4).
- Retry (qayta urinish): xato bo'lsa, so'rovni 2 marta qayta urinib ko'rish (bonus).
- Event loop tushunchasini ko'rsatish:
console.log+setTimeout+Promisetartibini bashorat qilib, tekshiring 2.9-bob.
Maslahatlar (hint)
- Ochiq API:
https://jsonplaceholder.typicode.com/users/1,/posts?userId=1,/comments?postId=1. - Parallel:
await Promise.all([malumotOl(u1), malumotOl(u2)]). - Vaqt o'lchash:
console.time("nom")...console.timeEnd("nom")0.5-bob. - Timeout:
Promise.race([fetch(url), timeout(5000)])(Misol 4). - Retry: tsikl +
try/catch, muvaffaqiyatdareturn, xatoda davom 2.12-bob. - Xato turlari:
!res.okHTTP;catchtarmoq/timeout.
"Tayyor" mezonlari (acceptance criteria)
-
fetch+res.ok+json+try/catchto'g'ri ishlaydi. - Ketma-ket zanjir (bog'liq so'rovlar) ishlaydi.
- Parallel (
Promise.all) ketma-ketdan tezroq (vaqt ko'rsatilgan). -
allSettledbilan ba'zisi xato bo'lsa ham davom etadi. -
racebilan timeout ishlaydi. - Tarmoq/HTTP/timeout xatolari alohida boshqariladi.
-
UnhandledPromiseRejectionyo'q (hammasi ushlangan).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda JS'ning eng muhim mavzularidan birini — asinxron dasturlashni o'rgandik:
- Sinxron (bloklaydi) vs asinxron (fonda, bloklamaydi — 0.5: event loop). JS bir thread'li, shuning uchun asinxronlik zarur.
- Callback callback hell; Promise (pending fulfilled/rejected,
.then/.catch/.finally) buni hal qildi. async/await— eng o'qishli;asyncdoim Promise qaytaradi,awaitkutadi (microtask — 2.9).fetch0.4-bob — Promise;res.oktekshiring +res.json()(ikki await).- Kombinatorlar:
Promise.all(parallel, hammasi),allSettled(har natija),race(birinchi/timeout),any. - Event loop: microtask (Promise) macrotask (setTimeout) dan oldin 2.9-bob.
Keyingi bob — 2.12-bob: Error handling — try/catch/finally, throw, custom error. Asinxron kodda try/catchni ishlatdik; endi xatolarni professional boshqarishni to'liq o'rganamiz. Xato — dasturning dushmani emas, balki uni mustahkam qiladigan vosita. To'g'ri error handling — havaskor va professional kodning eng aniq farqi.
Foydalanilgan rasmiy/ishonchli manbalar
- MDN Web Docs — Using promises,
async/await,Promise - MDN Web Docs —
Promise.all/allSettled/race/any - MDN Web Docs — Microtask guide, event loop (microtask vs macrotask)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!