Mundarija (34)
- Bu darsda
- 1. Nega bu kerak?
- 2. async funksiya
- 2.1 Doim Promise qaytaradi
- 2.2 async qayerga yoziladi
- 3. await
- 3.1 Natijani kutib olish
- 3.2 await funksiyani to'xtatadi, dasturni emas
- 3.3 Promise bo'lmagan qiymatni await qilish
- 3.4 Generator bilan aloqasi
- 4. Xatolar: try / catch / finally
- 4.1 Rad etilgan await — throw
- 4.2 Bitta try — bir nechta await
- 4.3 return va return await farqi
- 5. "Suzib yurgan" Promise
- 5.1 await ni unutish
- 5.2 Qachon await siz chaqirish mumkin
- 6. await qayerda ishlaydi
- 6.1 Faqat async funksiya ichida
- 6.2 Modulning eng yuqori darajasi
- 6.3 Asinxron IIFE
- 6.4 await using
- 7. Ko'p uchraydigan xatolar
- 7.1 await ni unutish
- 7.2 async ni "parallel" yoki "fon"da ishlaydi deb o'ylash
- 7.3 Har qatorga try/catch
- 7.4 Mustaqil ishlarni ketma-ket await qilish
- 8. Mashqlar
- 1-mashq (oson): Zanjirdan await ga
- 2-mashq (o'rta): Tartibni oldindan ayting
- 3-mashq (qiyin): Qayta urinish — sikl bilan
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript async / await: asinxron kodni sinxron kabi yozish
Qisqacha:
asyncfunksiya doim Promise qaytaradi:returnqiymati — bajarilish,throw— rad etish. Uning ichidaawait promisefunksiyani Promise hal bo'lguncha to'xtatadi va natijani qaytaradi:const stol = await stolTop(4);. Dastur esa to'xtamaydi — funksiyadan keyingi kod davom etadi. Rad etilganawait— oddiythrowkabi, unitry/catchushlaydi.
Bu darsda
asyncfunksiya nima qaytarishini vaawaitqayerda, qanday to'xtashini tushuntira olasiz.- Promise zanjirini
async/awaitbilan tekis, sinxron ko'rinishdagi kodga aylantira olasiz. - Asinxron xatolarni tanish
try/catch/finallybilan ushlay olasiz. - "Suzib yurgan" (floating) Promise xatosini tanib, tuzata olasiz.
awaitbor kodning chiqish tartibini event loop bo'yicha oldindan ayta olasiz.
Oldin bilishingiz kerak: Promise zanjiri, Promise asoslari, try / catch / finally.
1. Nega bu kerak?
Promise zanjiri piramidani tekisladi. Lekin uch joyda zanjir hamon noqulay.
Oldingi natijalar. Chekda ham stol raqami, ham buyurtma bo'lishi kerak. Tekis zanjirda stol faqat birinchi then da ko'rinadi — uni pastga yetkazish uchun obyektlar yig'ish yoki ichma-ich then kerak bo'ldi.
Shart va sikllar. "Stol topilmasa — ayvondan qidir", "uch marta qayta urin" — zanjirda bularni yozish uchun rekursiya kerak bo'ldi (qaytaUrin). Oddiy if va for ishlamaydi.
Xatolar. try / catch / finally darsida try asinxron xatoni ushlamasligini ko'rdik va "Promise'dagi xatolar uchun boshqa yo'l bor — 11-qismda" degan edik. Zanjirda o'sha "boshqa yo'l" — catch metodi. Lekin u tanish try/catch dan boshqacha yoziladi.
Asl orzu esa oddiy: asinxron kodni ham sinxron kod kabi — yuqoridan pastga, o'zgaruvchilar, if, for va try/catch bilan yozish. async/await aynan shuni beradi. U ES2017 da qo'shilgan va bugun asinxron kodning asosiy shakli.
Muhimi: async/await — yangi mexanizm emas. U Promise'ning ustiga qurilgan sintaksis. Ichida hamon o'sha Promise'lar, o'sha then va o'sha microtask navbati. Shuning uchun oldingi ikki dars bekor ketmaydi — ularsiz await xatolarini topib bo'lmaydi.
2. async funksiya
2.1 Doim Promise qaytaradi
Funksiya oldiga async kalit so'zini qo'ysangiz, u asinxron funksiya bo'ladi. Birinchi farq — u har doim Promise qaytaradi:
async function narxniOl() {
return 35000;
}
const natija = narxniOl();
console.log(natija);
console.log(natija instanceof Promise);
natija.then((narx) => console.log("then:", narx));Konsolda:
Promise { 35000 }
true
then: 35000Biz 35000 ni qaytardik, lekin chaqiruvchi Promise oldi — shu qiymat bilan bajarilgan. Uni then bilan o'qiymiz, xuddi oldingi darslardagidek. (instanceof — obyekt shu klassning nusxasimi: Object.create va instanceof.)
throw esa rad etilgan Promise'ga aylanadi:
async function stolTop(odam) {
if (odam > 20) {
throw new Error("Bunday katta stol yo'q");
}
return 5;
}
stolTop(25)
.then((stol) => console.log("Stol:", stol))
.catch((xato) => console.log("Xato:", xato.message));
console.log("Funksiya chaqirildi, dastur davom etmoqda");Konsolda:
Funksiya chaqirildi, dastur davom etmoqda
Xato: Bunday katta stol yo'qthrow dastur to'xtatmadi va chaqiruv joyida ham xato chiqarmadi. U Promise'ning rad etilishiga aylandi va catch ga keldi. Bu Promise zanjiri dagi qoidaning aynan o'zi: async funksiya — xuddi then callback'i kabi — natijasini Promise'ga o'raydi.
async funksiya ichida |
Chaqiruvchi oladi |
|---|---|
return qiymat |
shu qiymat bilan bajarilgan Promise |
| hech narsa qaytarmaydi | undefined bilan bajarilgan Promise |
return promise |
o'sha Promise kabi hal bo'ladigan Promise |
throw xato |
shu xato bilan rad etilgan Promise |
2.2 async qayerga yoziladi
async har qanday funksiya shakliga qo'yiladi:
async function bronQil(stol) { ... } // e'lon
const bronQil = async function (stol) { ... }; // ifoda
const bronQil = async (stol) => { ... }; // arrow
const kassa = {
async tolovQil(summa) { ... }, // obyekt metodi
};
class Oshxona {
async tayyorla(taom) { ... } // klass metodi
}Arrow funksiyada async qavslardan oldin turadi: async (stol) => .... Bitta parametrli qisqa shakl ham bor: async stol => ....
Tekshirib ko'ring:
async function f() {}—f()nima qaytaradi?
Javob
undefined bilan bajarilgan Promise — Promise { undefined }. Funksiya hech narsa qaytarmadi, lekin async bo'lgani uchun natija baribir Promise'ga o'raldi.
3. await
3.1 Natijani kutib olish
await — faqat async funksiya ichida ishlatiladigan operator. await promise — "shu Promise hal bo'lguncha funksiyani to'xtat; bajarilsa — uning qiymatini ber".
Promise zanjiri dagi to'rt qadamli bronni qayta yozamiz:
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function stolTop(odam) {
await kut(100);
if (odam > 20) throw new Error("Bunday katta stol yo'q");
return 5;
}
async function bronQil(stol) {
await kut(100);
return `${stol}-stol, 19:00`;
}
async function chekYoz(buyurtma) {
await kut(100);
return `${buyurtma}: 35000 so'm`;
}
async function bronJarayoni(odam) {
const stol = await stolTop(odam);
const bron = await bronQil(stol);
const chek = await chekYoz(`${bron}, osh`);
console.log("Chek:", chek);
console.log("Stol raqami alohida:", stol);
}
bronJarayoni(4);Konsolda:
Chek: 5-stol, 19:00, osh: 35000 so'm
Stol raqami alohida: 5bronJarayoni ga qarang: then yo'q, callback yo'q. Har qator oldingisi tugagach bajariladi — xuddi sinxron kod kabi. Natijalar oddiy const o'zgaruvchilarda. Oxirgi qatorda stol hamon ko'rinadi — zanjirdagi "oldingi natija" muammosi o'z-o'zidan yo'qoldi.
Bu ko'rinish aldamasin: kod sinxron ko'rinadi, lekin sinxron emas. Har await da bronJarayoni to'xtaydi va stekni bo'shatadi. Uch qadam orasida 300 ms o'tadi — shu vaqt ichida boshqa kod, bosishlar va taymerlar bemalol ishlaydi. Sinxron "kutish" (Sinxron va asinxron kod dagi bo'sh sikl) esa sahifani qotirardi.
Yordamchi funksiyalar ham async bo'ldi: kut(100) ni kutib, keyin natija qaytaradi. kut esa oddiy funksiya — u Promise'ni new Promise bilan yasaydi. Taymer kabi callback'li API'ni Promise'ga aylantirishda new Promise hamon kerak — async buni qila olmaydi.
3.2 await funksiyani to'xtatadi, dasturni emas
Eng muhim tushuncha. await da faqat shu funksiya to'xtaydi. Funksiyani chaqirgan kod esa davom etadi. Ishga tushirishdan oldin tartibni o'zingiz ayting:
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function oshDamla() {
console.log("2. Qozon yondi");
await kut(300);
console.log("4. Osh tayyor");
}
console.log("1. Buyurtma");
oshDamla();
console.log("3. Choy quyildi");Konsolda:
1. Buyurtma
2. Qozon yondi
3. Choy quyildi
4. Osh tayyorKodda "4" "3" dan yuqorida yozilgan, lekin keyin chiqdi. Qadamma-qadam kuzating — ayniqsa oshDamla stekdan qachon chiqib, qachon qaytishiga:
Uch qoida:
asyncfunksiya birinchiawaitgacha sinxron ishlaydi — "2" darhol chiqdi. Bu executor'ning darhol ishlashiga o'xshaydi (Promise asoslari).awaitda funksiya stekdan chiqadi. Stek bo'shaydi, boshqa kod ishlaydi — bloklash yo'q.- Promise hal bo'lgach, funksiyaning davomi microtask sifatida qaytadi — xuddi
thencallback'i kabi.
Aslida await dan keyingi hamma qatorlar — yashirin then callback'i. oshDamla ni shunday tasavvur qilsangiz bo'ladi: console.log("2..."); return kut(300).then(() => console.log("4..."));. Til buni siz uchun yozadi.
3.3 Promise bo'lmagan qiymatni await qilish
await 35000 ham ishlaydi — qiymat darhol bajarilgan Promise'ga o'raladi. Lekin funksiya baribir to'xtaydi va davomi microtask'da keladi:
async function narx() {
console.log("2. funksiya ichida");
const n = await 35000;
console.log("4. await'dan keyin:", n);
}
console.log("1");
narx();
console.log("3");Konsolda:
1
2. funksiya ichida
3
4. await'dan keyin: 35000Kutadigan narsa yo'q edi, lekin "4" baribir "3" dan keyin chiqdi. await — doim "to'xta va microtask'da davom et". Bu ham Promise'ning "doim asinxron" kafolati: await dan keyingi kod hech qachon chaqiruvchidan oldin ishlamaydi.
Tekshirib ko'ring:
oshDamladaawait kut(300)o'rnigakut(300)(await'siz) yozilsa, tartib qanday bo'ladi?
Javob
1, 2, 4, 3. await bo'lmasa, funksiya to'xtamaydi: taymer qo'yiladi, lekin "4. Osh tayyor" darhol, sinxron chiqadi. Keyin funksiya tugaydi va skript "3" ni chiqaradi. Osh "tayyor" bo'ldi, qozon esa hali qaynayapti — bu xato.
3.4 Generator bilan aloqasi
Generatorlar chuqur darsida ijroEt ijrochisini yozgan edik: generator yield bilan "narx kerak" deydi va to'xtaydi, ijrochi javobni topib, next(javob) bilan uni davom ettiradi. O'shanda "async/await shu g'oyani tilning o'ziga olib kirdi" degan edik. Endi solishtiring:
| Generator + ijrochi | async funksiya |
|---|---|
function* |
async function |
const osh = yield topshiriq; |
const osh = await promise; |
ijrochi next(javob) bilan davom ettiradi |
dvigatel Promise bajarilganda davom ettiradi |
| ijrochini o'zingiz yozasiz | ijrochi tilning ichida |
await — "Promise'ni yield qil, bajarilganda meni next(natija) bilan uyg'ot" degani. Funksiyaning o'zgaruvchilari va qaysi qatorda to'xtagani generatordagidek saqlanib qoladi. 2017 gacha dasturchilar aynan shu naqshni kutubxona bilan (co) ishlatgan.
4. Xatolar: try / catch / finally
4.1 Rad etilgan await — throw
await qilingan Promise rad etilsa, await turgan qatorda xato tashlanadi — xuddi u yerda throw yozilgandek. Demak uni oddiy try/catch ushlaydi:
function narxniSora(taom) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (taom === "osh") resolve(35000);
else reject(new Error(`Menyuda yo'q: ${taom}`));
}, 100);
});
}
async function narxniKorsat(taom) {
console.log("Yuklanmoqda...");
try {
const narx = await narxniSora(taom);
console.log(`${taom}: ${narx} so'm`);
} catch (xato) {
console.log("Xato:", xato.message);
} finally {
console.log("Yuklanish belgisi yashirildi");
}
}
narxniKorsat("palov");Konsolda:
Yuklanmoqda...
Xato: Menyuda yo'q: palov
Yuklanish belgisi yashirilditry / catch / finally darsidagi va'da bajarildi. O'shanda try taymer ichidagi xatoni ushlamagan edi: try taymerni qo'yib, tugab bo'lgan edi. Bu yerda esa await funksiyani try blokining ichida to'xtatadi. Xato kelganda funksiya hamon try ichida — shuning uchun catch uni ushlaydi.
try ichidagi await dan keyingi qator (console.log(...narx...)) bajarilmadi — sinxron throw dagi kabi. finally esa ikkala holatda ham ishlaydi: "osh" bilan sinab ko'ring.
4.2 Bitta try — bir nechta await
Bitta try ichida bir nechta await bo'lsa, ulardan istalganining xatosi bitta catch ga keladi. Bu zanjir oxiridagi bitta .catch() ning aynan o'zi:
async function bronJarayoni(odam) {
try {
const stol = await stolTop(odam);
const bron = await bronQil(stol);
return await chekYoz(bron);
} catch (xato) {
console.log("Bron bo'lmadi:", xato.message);
return null;
}
}Agar har qadam uchun alohida munosabat kerak bo'lsa (masalan stol topilmasa — ayvondan qidirish), shu qadamni alohida try ga o'rang. Endi bu oddiy if/try bilan yoziladi — zanjirdagi kabi rekursiya shart emas.
Tekshirib ko'ring:
bronJarayoni(25)chaqirildi (stolTop20 dan ko'pga xato beradi).bronQilchaqiriladimi va funksiya nima qaytaradi?
Javob
Yo'q. Birinchi await qatorida xato tashlanadi, try ning qolgan qatorlari o'tkazib yuboriladi. catch "Bron bo'lmadi: ..." deb yozadi va null qaytaradi — demak bronJarayoni(25) null bilan bajarilgan Promise qaytaradi, rad etilgan emas.
4.3 return va return await farqi
Oxirgi kodda return await chekYoz(bron) yozdik. Shunchaki return chekYoz(bron) bo'lsa-chi? try dan tashqarida farqi yo'q. try ichida esa bor:
async function serverdanOl() {
throw new Error("Server javob bermadi");
}
async function birinchi() {
try {
return serverdanOl();
} catch {
return "zaxira narx";
}
}
async function ikkinchi() {
try {
return await serverdanOl();
} catch {
return "zaxira narx";
}
}
ikkinchi().then((x) => console.log("ikkinchi:", x));
birinchi()
.then((x) => console.log("birinchi:", x))
.catch((xato) => console.log("birinchi xato:", xato.message));Konsolda:
ikkinchi: zaxira narx
birinchi xato: Server javob bermadiNega shunday? try faqat tashlangan (throw) xatoni ushlaydi. birinchi da return rad etilgan Promise'ni ochmasdan, "qutisi bilan" chaqiruvchiga uzatdi. Hech narsa tashlanmadi — catch ishlamadi, xato tashqaridagi .catch ga ketdi. ikkinchi da esa await Promise'ni try ichida ochdi. Rad etilgan Promise await da throw ga aylandi va catch uni ushladi. Qoida: try ichida Promise qaytarsangiz — return await yozing.
catch dan keyin (xato) yo'qligiga e'tibor bering: xato obyekti kerak bo'lmasa, uni tashlab ketish mumkin (try / catch / finally).
Tekshirib ko'ring:
narxniKorsat("osh")chaqirilsa, konsolda qaysi uch qator chiqadi?
Javob
Yuklanmoqda..., osh: 35000 so'm, Yuklanish belgisi yashirildi. Promise bajarildi, await qiymatni berdi, try oxirigacha ishladi, catch o'tkazib yuborildi, finally baribir ishladi.
5. "Suzib yurgan" Promise
5.1 await ni unutish
async funksiyani await siz chaqirsangiz, u ishlaydi, lekin uning natijasi va xatosi hech kimga kerak bo'lmay qoladi. Bunday Promise suzib yurgan (floating) Promise deyiladi — u "hech kimga bog'lanmagan":
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function saqla() {
await kut(100);
throw new Error("Disk to'la");
}
async function tugmaBosildi() {
try {
saqla();
console.log("Saqlandi!");
} catch (xato) {
console.log("Saqlanmadi:", xato.message);
}
}
tugmaBosildi();Node 24 da (fayl yo'li qisqartirildi):
Saqlandi!
file:///C:/.../11/suzuvchi.mjs:6
throw new Error("Disk to'la");
^
Error: Disk to'la
at saqla (file:///C:/.../11/suzuvchi.mjs:6:9)
Node.js v24.21.0Ikki yomon narsa birdaniga. Birinchisi, foydalanuvchi "Saqlandi!" ni ko'rdi — saqlash hali boshlanmagan bo'lsa ham. Ikkinchisi, try/catch xatoni ushlamadi va dastur to'xtadi. Sabab bitta: await yo'q. Funksiya saqla() dan Promise oldi, unga qaramadi va try dan chiqib ketdi. Xato 100 ms dan keyin, hech kim kutmagan Promise'da chiqdi — ushlanmagan rad etilish.
Tuzatish: await saqla();. Shunda "Saqlandi!" faqat haqiqatan saqlangandan keyin chiqadi, xato esa catch ga tushadi.
5.2 Qachon await siz chaqirish mumkin
Ba'zan natijani kutish haqiqatan kerak emas: masalan, statistika yuborish. Lekin xatoni baribir kimdir ushlashi kerak:
statistikaYubor(sahifa).catch((xato) => console.warn(xato.message));Qoida: har Promise yo await qilinadi, yo return qilinadi, yo .catch() oladi. Katta loyihalarda buni maxsus tekshiruvchi vosita kuzatadi. ESLint — kodni avtomatik tekshiradigan dastur, TypeScript — JavaScript'ning turlar qo'shilgan varianti. Ularning no-floating-promises qoidasi "suzib yurgan" Promise'ni topib, ogohlantiradi. Ikkalasi 15–16-qismlarda; hozir bilish shart emas.
Yana bir belgi. async funksiya natijasini await siz chiqarsangiz, konsolda qiymat emas, Promise ko'rinadi:
async function narxniOl() {
await null;
return 35000;
}
const narx = narxniOl();
console.log(narx);Konsolda:
Promise { <pending> }Konsolda Promise { <pending> } ko'rsangiz — deyarli doim qayerdadir await unutilgan.
Tekshirib ko'ring: Ofitsiant Otabekning ilovasida
async function buyurtmaniYubor()bor. Tugma tinglovchisida ubuyurtmaniYubor(); ekranniTozala();deb chaqirilgan. Buyurtma yuborilmay qolsa, Otabek buni biladimi?
Javob
Yo'q. await yo'q — Promise suzib yuradi. Ekran darhol tozalanadi, yuborish xatosi esa hech qayerda ko'rsatilmaydi: brauzer konsolga Uncaught (in promise) yozadi, Otabek esa uni ko'rmaydi. Tuzatish: tinglovchini async qilib, try { await buyurtmaniYubor(); ekranniTozala(); } catch (xato) { ... } — xatoni ekranda ko'rsatish.
6. await qayerda ishlaydi
6.1 Faqat async funksiya ichida
Oddiy funksiyada await — sintaksis xatosi. Kod umuman ishga tushmaydi:
async function narxniOl() {
return 35000;
}
function chekYoz() {
const narx = await narxniOl();
}Brauzerda va oddiy skriptda:
SyntaxError: await is only valid in async functions and the top level bodies of modulesTarjimasi: "await faqat async funksiyalarda va modullarning eng yuqori darajasida ishlaydi". Node'da .mjs faylda xabar boshqacha — SyntaxError: Unexpected reserved word ("kutilmagan band qilingan so'z"). Modulda await — tilning band so'zi, uni oddiy funksiyada uchratgan Node "bu yerda bu so'zni kutmagan edim" deydi. Ikkala xabarning tuzatishi bitta: await turgan funksiyaga async qo'shing.
async faqat eng yaqin funksiyaga ta'sir qiladi. async funksiya ichidagi oddiy callback'da await yozsangiz — yana shu xato:
async function hammasiniOl(taomlar) {
taomlar.forEach((taom) => {
const narx = await narxniSora(taom); // SyntaxError
});
}Callback'ni async qilsangiz, xato yo'qoladi — lekin yangi, ancha ayyorroq muammo paydo bo'ladi. Uni keyingi darsda, Ketma-ket va parallel bajarish da ko'ramiz.
6.2 Modulning eng yuqori darajasi
Xabardagi ikkinchi qism — "modullarning eng yuqori darajasi". ES modulda (.mjs, type="module") await ni funksiyadan tashqarida ham yozish mumkin. Bu top-level await deyiladi va Dinamik import() va top-level await darsida o'rganiladi — hozir bilish shart emas. Shu paytgacha kodimizda bitta joy await siz qoladi — eng tashqi chaqiruv: bronJarayoni(4);.
6.3 Asinxron IIFE
Oddiy skriptda (modul bo'lmagan) await ni darhol ishlatish kerak bo'lsa, eski usul bor — asinxron IIFE. IIFE va funksiya obyekt sifatida darsida "(async () => { ... })() shaklini async/await darsida ko'ramiz" degan edik:
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
(async () => {
console.log("Kassa ochilmoqda...");
await kut(200);
console.log("Kassa ochiq");
})();Konsolda:
Kassa ochilmoqda...
Kassa ochiqAsync arrow funksiya yaratiladi va shu zahoti chaqiriladi. Uning ichida await erkin ishlaydi. Eski kodda va Node skriptlarida bu shaklni tez-tez uchratasiz.
IIFE darsidagi tuzoqni eslang: oldingi qator ; siz tugasa va keyingi qator ( bilan boshlansa, JavaScript ikkalasini bitta ifoda deb o'qiydi va oldingi qiymatni funksiya kabi chaqirmoqchi bo'ladi. Asinxron IIFE'da ham xuddi shunday. Shuning uchun ba'zi kodlarda boshida nuqta-vergulli ;(async () => { ... })(); ko'rinishini uchratasiz.
Tekshirib ko'ring: IIFE ichidagi
await kut(200)butun skriptni 200 ms to'xtatadimi? IIFE'dan keyinconsole.log("keyingi qator")bo'lsa, u qachon chiqadi?
Javob
Yo'q, faqat IIFE'ning o'zi to'xtaydi. "keyingi qator" "Kassa ochilmoqda..." dan keyin, lekin "Kassa ochiq" dan oldin chiqadi: await da funksiya stekdan chiqadi va skript davom etadi.
6.4 await using
Resurslarni aniq boshqarish: using darsida await using shaklini ko'rgan edik — "await ni 11-qismda o'rganamiz" deb. Endi uni to'liq tushunamiz: blok tugaganda resursning [Symbol.asyncDispose]() metodi chaqiriladi va u qaytargan Promise kutiladi. Buni faqat async funksiya (yoki modul) ichida qilish mumkin — chunki kutish kerak.
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function ulanishOch(nomi) {
console.log(`${nomi}: ochildi`);
return {
async [Symbol.asyncDispose]() {
await kut(100);
console.log(`${nomi}: yopildi`);
},
};
}
async function hisobotYoz() {
await using baza = ulanishOch("Baza");
console.log("Hisobot yozilmoqda");
}
hisobotYoz().then(() => console.log("Tugadi"));Konsolda:
Baza: ochildi
Hisobot yozilmoqda
Baza: yopildi
Tugadi"Tugadi" faqat baza yopilgandan keyin chiqdi: hisobotYoz ning Promise'i yopish tugashini kutdi. [Symbol.asyncDispose] ning o'zi ham async metod — u ichida await qiladi. Blok Node 24 da sinalgan; brauzerlarda bu imkoniyat hali hammasida yo'q.
7. Ko'p uchraydigan xatolar
7.1 await ni unutish
«Suzib yurgan» Promise bo'limidagi xato. Belgilari: konsolda Promise { <pending> }, "Saqlandi!" kabi xabarlar juda erta chiqadi, try/catch xatoni ushlamaydi. Yana bir ayyor ko'rinishi — shartda:
if (stolBormi(4)) { ... } // doim true!stolBormi — async funksiya, u Promise qaytaradi. Promise esa obyekt — doim truthy (Boolean va truthy/falsy). false qaytsa ham shart bajariladi. Tuzatish: if (await stolBormi(4)).
7.2 async ni "parallel" yoki "fon"da ishlaydi deb o'ylash
async funksiya alohida thread'da — boshqa "ishchi"da (Sinxron va asinxron kod) — ishlamaydi. U birinchi await gacha oddiy, sinxron bajariladi. Ichida og'ir sinxron sikl bo'lsa — sahifa baribir qotadi, xuddi Promise asoslari dagi Sardorning hisobidek. async faqat kutishni samarali qiladi, hisobni emas.
7.3 Har qatorga try/catch
let stol;
try { stol = await stolTop(4); } catch (x) { console.log(x); }
let bron;
try { bron = await bronQil(stol); } catch (x) { console.log(x); }Birinchi qadam xato bersa, ikkinchisi undefined stol bilan baribir bajariladi. Tuzatish: bog'liq qadamlarni bitta try ga oling — xato bo'lsa, qolgani o'tkazib yuborilsin. Alohida try faqat o'sha qadamning xatosiga boshqacha munosabat (zaxira, qayta urinish) kerak bo'lganda.
7.4 Mustaqil ishlarni ketma-ket await qilish
const osh = await narxniSora("osh");
const manti = await narxniSora("manti");Bu to'g'ri ishlaydi, lekin sekin: "manti" so'rovi "osh" javobini kutib turadi, garchi ular bir-biriga bog'liq bo'lmasa ham. Ikkalasi 200 ms dan bo'lsa — jami 400 ms. Buni qanday 200 ms ga tushirish — keyingi darsning asosiy mavzusi.
8. Mashqlar
1-mashq (oson): Zanjirdan await ga
Promise zanjiri dagi choy zanjirini async funksiya bilan qayta yozing. suvQaynat, choySol, damla — o'zgarmaydi. choyTayyorla() nomli async funksiya ularni ketma-ket await qilsin, natijani chiqarsin, xato bo'lsa — try/catch bilan Xato: ... deb yozsin.
Yechim
function suvQaynat() {
return new Promise((resolve) => {
setTimeout(() => resolve("qaynoq suv"), 100);
});
}
function choySol(suv) {
return new Promise((resolve) => {
setTimeout(() => resolve(`${suv} + ko'k choy`), 100);
});
}
function damla(choynak) {
return new Promise((resolve) => {
setTimeout(() => resolve(`${choynak} (damlandi)`), 100);
});
}
async function choyTayyorla() {
try {
const suv = await suvQaynat();
const choynak = await choySol(suv);
const choy = await damla(choynak);
console.log("Tayyor:", choy);
} catch (xato) {
console.log("Xato:", xato.message);
}
}
choyTayyorla();Konsolda:
Tayyor: qaynoq suv + ko'k choy (damlandi)Har oraliq natija o'z nomiga ega: suv, choynak, choy. Zanjirda ular faqat then parametrlari edi.
2-mashq (o'rta): Tartibni oldindan ayting
Avval qog'ozda yozing, keyin tekshiring. Ishora: async funksiya birinchi await gacha sinxron; await dan keyingi qism — microtask.
async function birinchi() {
console.log("B");
await null;
console.log("D");
}
console.log("A");
birinchi();
new Promise((resolve) => {
console.log("C");
resolve();
}).then(() => console.log("E"));
console.log("F");Yechim
Konsolda:
A
B
C
F
D
ESinxronlar: A, B (birinchi ichida, await gacha), C (executor), F. await null — birinchi ning davomi microtask navbatiga birinchi bo'lib tushdi. Keyin then callback'i — ikkinchi. Shuning uchun D, keyin E.
3-mashq (qiyin): Qayta urinish — sikl bilan
Promise zanjiri dagi 3-mashqda qaytaUrin ni rekursiya bilan yozgan edik. Endi uni async funksiya, for sikli va try/catch bilan qayta yozing: kurs/mashqlar/11/07-async/qaytaUrin.mjs. Qo'shimcha talab: urinishlar orasida 100 * urinish ms kutilsin (birinchidan keyin 100, ikkinchidan keyin 200 ...) — kut yordamchisi bilan. Sinov — o'sha ishonchsizServer.
Yechim
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
let chaqiruv = 0;
function ishonchsizServer() {
chaqiruv++;
return new Promise((resolve, reject) => {
setTimeout(() => {
if (chaqiruv < 3) reject(new Error(`${chaqiruv}-urinish xato`));
else resolve(`${chaqiruv}-urinishda narx: 28000`);
}, 100);
});
}
async function qaytaUrin(ish, marta) {
for (let urinish = 1; ; urinish++) {
try {
return await ish();
} catch (xato) {
console.log("Xato:", xato.message);
if (urinish >= marta) throw xato;
console.log(`${100 * urinish} ms kutamiz`);
await kut(100 * urinish);
}
}
}
async function asosiy() {
try {
const natija = await qaytaUrin(ishonchsizServer, 5);
console.log(natija);
} catch (xato) {
console.log("Taslim:", xato.message);
}
}
asosiy();Konsolda:
Xato: 1-urinish xato
100 ms kutamiz
Xato: 2-urinish xato
200 ms kutamiz
3-urinishda narx: 28000Uchta muhim joy:
return await ish()—tryichida! Oddiyreturn ish()bo'lsa, rad etishcatchga tushmasdi va birinchi xatodayoq tashqariga chiqardi («returnvareturn awaitfarqi» bo'limi).for (let urinish = 1; ; urinish++)— sikl shartsiz: undanreturn(muvaffaqiyat) yokithrow(urinishlar tugadi) bilan chiqiladi.await kut(...)sikl ichida — siklni ham to'xtatadi. Sinxron kodda bunday "kutish" uchun bo'sh sikl kerak bo'lardi va sahifa qotardi (Sinxron va asinxron kod). Bu yerda esa kutish paytida stek bo'sh.
git add 11/07-async/qaytaUrin.mjs
git commit -m "11/07: qaytaUrin — async/await va for bilan"9. Real ishda
- Asosiy shakl. Bugungi frontend va backend kodning katta qismi
async/awaitda: React'da ma'lumot yuklash, Express va NestJS'da so'rov ishlovchilari, ma'lumotlar bazasi so'rovlari (await db.query(...)). Tarmoq so'rovi ham shunday ko'rinadi:const javob = await fetch(url)—fetchasoslari da o'rganasiz. thenhamon bor. Bir qatorli o'zgartirishlar,catchbilan zaxira qiymat, kutubxona ichlari — zanjirni ham o'qiy olishingiz kerak. Ikkalasi bitta Promise ustida ishlaydi va aralash yozilishi mumkin:const narx = await narxniSora("osh").catch(() => 28000);.- Kod sharhi. "Bu yerda
awaitunutilmaganmi?", "Bu xato kimga ketadi?" — asinxron kodli PR'larda eng ko'p beriladigan savollar. - Intervyu. "
asyncfunksiya nima qaytaradi?", "awaitthread'ni bloklaydimi?", "Bu kodning chiqish tartibi qanday?" (async+setTimeout+thenaralash), "returnvareturn awaitfarqi" — juda tez-tez.
Xulosa
asyncfunksiya doim Promise qaytaradi:return— bajarilish,throw— rad etish.await promisefaqat shu funksiyani to'xtatadi; chaqiruvchi davom etadi, stek bo'shaydi. Davomi — microtask.asyncfunksiya birinchiawaitgacha sinxron ishlaydi;awaitPromise bo'lmagan qiymatda ham to'xtaydi.- Rad etilgan
await—throw: unitry/catch/finallyushlaydi;tryichidareturn awaityozing. - Har Promise yo
await, yoreturn, yo.catch()qilinsin — aks holda u "suzib yuradi" va xatosi yo'qoladi. awaitfaqatasyncfunksiya ichida (yoki modulning yuqori darajasida) ishlaydi.
Keyingi dars: Ketma-ket va parallel bajarish — mustaqil ishlarni bir vaqtda boshlab, Promise.all bilan kutish; sikldagi await va forEach + async tuzog'i.
Manbalar
- ECMAScript spetsifikatsiyasi: "Async Function Definitions", "Await" — tc39.es/ecma262
- MDN: "async function", "await", "Using promises" — developer.mozilla.org
- V8 blogi: "Faster async functions and promises" (await qadamlari) — v8.dev
- typescript-eslint: "no-floating-promises" qoidasi — typescript-eslint.io
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!