Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Promise nima?
- 2.1 Ta'rif va uch holat
- 2.2 Promise'ni ko'rish
- 3. Promise yaratish: new Promise
- 3.1 Executor, resolve va reject
- 3.2 Executor darhol, sinxron ishlaydi
- 3.3 Executor ichidagi throw
- 3.4 Promise ishni boshqarmaydi — u ishni kuzatadi
- 4. Natijani olish: then, catch, finally
- 4.1 then — bajarilganda
- 4.2 catch — rad etilganda
- 4.3 finally — har qanday holatda
- 5. then qachon chaqiriladi: microtask
- 5.1 Qadamma-qadam
- 5.2 Allaqachon hal bo'lgan Promise
- 5.3 Kech qo'shilgan then ham natijani oladi
- 6. Promise callback muammolarini qanday hal qiladi
- 6.1 Faqat bir marta
- 6.2 Doim asinxron
- 6.3 Xato — alohida yo'ldan
- 7. Ko'p uchraydigan xatolar
- 7.1 Ushlanmagan rad etilish
- 7.2 resolve ni hech qachon chaqirmaslik
- 7.3 then dan natijani tashqariga olib chiqish
- 7.4 then ga funksiya o'rniga chaqiruv berish
- 7.5 "Promise'ga o'rasam — og'ir ish asinxron bo'ladi"
- 8. Mashqlar
- 1-mashq (oson): Bron Promise bilan
- 2-mashq (o'rta): Tartibni oldindan ayting
- 3-mashq (qiyin): Callback'li funksiyani Promise'ga o'rash
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript Promise asoslari: kutilmoqda, bajarildi, rad etildi
Qisqacha: Promise — kelajakda tayyor bo'ladigan natija uchun obyekt. U uch holatdan birida bo'ladi: kutilmoqda (pending), bajarildi (fulfilled) yoki rad etildi (rejected). Yaratish:
new Promise((resolve, reject) => ...), natijani olish:chek.then(...), xatoni olish:chek.catch(...). Promise faqat bir marta hal bo'ladi vathencallback'lari doim asinxron — microtask navbati orqali — chaqiriladi.
Bu darsda
- Promise'ning uch holatini va "hal bo'ldi" (settled) nima ekanini tushuntira olasiz.
new Promisebilan o'z asinxron funksiyangizni Promise qaytaradigan qilib yoza olasiz.- Natijani
then, xatonicatchbilan olasiz,finallyni qachon ishlatishni bilasiz. - Promise callback'lar muammolarini — ikki marta chaqirish, "goh sinxron, goh asinxron" — qanday hal qilishini ko'rasiz.
thencallback'i qachon bajarilishini event loop navbatlari bo'yicha oldindan ayta olasiz.
Oldin bilishingiz kerak: Callbacklar va callback hell, Event loop, throw va Error obyekti.
1. Nega bu kerak?
Callbacklar va callback hell darsida callback'larning uchta og'riqli joyini ko'rdik:
- Bog'liq ishlar ichma-ich piramidaga aylanadi.
- Callback'ni begona kodga berasiz va u uni ikki marta chaqirishi mumkin — Dilshod aka bitta osh uchun ikki marta "to'ladi".
- Callback goh sinxron, goh asinxron chaqiriladi va kod tartibi buziladi ("Zalgo").
Hammasining ildizi bitta: asinxron funksiya natijani qaytarmaydi, balki sizning funksiyangizni chaqiradi. Boshqaruv uning qo'lida.
Endi «Bahor»ning yangi kassasini tasavvur qiling. Dilshod aka osh buyurtma qiladi. Kassir unga darhol chek beradi: "Buyurtmangiz raqami — 47. Tayyor bo'lganda ekranda chiqadi". Osh hali yo'q, lekin chek hozir Dilshod akaning qo'lida. U chekni cho'ntagiga solib, choy ichishga ketishi mumkin.
Chekning uch holati bor:
- tayyorlanmoqda — osh hali qozonda;
- tayyor — ekranda "47" yondi, oshni olish mumkin;
- bekor qilindi — osh tugab qoldi, kassir sababini aytadi.
Va chekning ikki muhim xususiyati bor. Birinchisi, "tayyor" bo'lgan chek qaytib "tayyorlanmoqda" bo'lmaydi va "bekor qilindi" ga o'tmaydi. Ikkinchisi, chek Dilshod akaning qo'lida. Oshxona uni chaqirmaydi — u o'zi xohlagan paytda chekka qaraydi.
JavaScript'da shu chek — Promise. Bugungi dars shu haqida.
2. Promise nima?
2.1 Ta'rif va uch holat
Promise — asinxron ishning kelajakdagi natijasini ifodalaydigan obyekt. Inglizcha so'zma-so'z "va'da" degani, lekin kursda atama inglizchaligicha qoladi: dasturchilar shunday aytadi.
Promise har doim uch holatdan birida bo'ladi:
| Holat | Inglizcha | Ma'nosi |
|---|---|---|
| kutilmoqda | pending | ish hali tugamagan, natija yo'q |
| bajarildi | fulfilled | ish muvaffaqiyatli tugadi, qiymat bor |
| rad etildi | rejected | ish xato bilan tugadi, sabab (odatda Error) bor |
Promise "bajarildi" yoki "rad etildi" holatiga o'tsa, u hal bo'ldi (settled) deyiladi. Hal bo'lgan Promise boshqa hech qachon o'zgarmaydi.
stateDiagram-v2
direction LR
state "kutilmoqda (pending)" as K
state "bajarildi (fulfilled)" as B
state "rad etildi (rejected)" as R
[*] --> K
K --> B: resolve(qiymat)
K --> R: reject(xato)Diagrammaga qarang: strelkalar faqat "kutilmoqda" dan chiqadi. "Bajarildi" va "rad etildi" — oxirgi bekatlar, ulardan yo'l yo'q.
2.2 Promise'ni ko'rish
Promise — oddiy obyekt. Uni o'zgaruvchiga saqlash, funksiyaga berish, console.log bilan chiqarish mumkin. Yaratishni keyingi bo'limda batafsil ko'ramiz, hozir faqat holatlarga qarang:
const chek = new Promise((resolve) => {
setTimeout(() => resolve(35000), 100);
});
console.log(chek);
setTimeout(() => console.log(chek), 200);Konsolda:
Promise { <pending> }
Promise { 35000 }Birinchi console.log darhol ishladi — taymer hali tugamagan, Promise kutilmoqda. 200 ms dan keyin esa u bajarildi, ichida qiymat — 35000. Node bajarilgan Promise'ni ichidagi qiymat bilan ko'rsatadi.
Brauzer konsoli boshqacha yozadi: Promise {<pending>}, ochsangiz esa [[PromiseState]]: "fulfilled" va [[PromiseResult]]: 35000. Ma'nosi bir xil.
Tekshirib ko'ring: Promise "bajarildi" holatidan "rad etildi" holatiga o'ta oladimi?
Javob
Yo'q. "Bajarildi" va "rad etildi" — ikkalasi ham hal bo'lgan holat, Promise ulardan chiqmaydi. Faqat "kutilmoqda" dan bir marta, ikki yo'lning biriga o'tiladi.
3. Promise yaratish: new Promise
3.1 Executor, resolve va reject
Promise'ni new Promise(...) bilan yaratamiz. Unga bitta funksiya beriladi — u executor deyiladi: asinxron ishni boshlab beradigan funksiya. Atama inglizchaligicha qoladi, dasturchilar shunday aytadi. «Bahor» tilida executor — kassir chekni bergandan keyin oshxonada boshlangan ish: qozon yonadi, osh pishadi.
Executor ikki parametr oladi:
resolve(qiymat)— "ish bajarildi, natija mana bu". Promise "bajarildi" holatiga o'tadi.reject(xato)— "ish bajarilmadi, sababi mana bu". Promise "rad etildi" holatiga o'tadi.
Chek misolida resolve — ekranda "47" raqamining yonishi, reject — "osh tugab qoldi" degan xabar. Ikkalasini ham Promise'ning o'zi tayyorlab, executor'ga beradi. Siz faqat ish tugaganda ulardan birini chaqirasiz. Nomlarini o'zingiz tanlashingiz mumkin, lekin resolve va reject — hamma joyda qabul qilingan nom. Biz ham shunday yozamiz.
Callbacklar darsidagi narxniSora ni Promise qaytaradigan qilib qayta yozamiz:
const menyu = { osh: 35000, manti: 30000 };
function narxniSora(taom) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (!Object.hasOwn(menyu, taom)) {
reject(new Error(`Menyuda yo'q: ${taom}`));
return;
}
resolve(menyu[taom]);
}, 200);
});
}
const chek = narxniSora("manti");
console.log(chek);Konsolda:
Promise { <pending> }Farqqa qarang. Eski narxniSora(taom, callback) hech narsa qaytarmasdi. Yangisi esa callback olmaydi va darhol obyekt qaytaradi — chek. Natija hali yo'q, lekin chek bizning qo'limizda.
Ichida esa tanish kod: o'sha setTimeout, o'sha tekshiruv. Faqat callback(new Error(...)) o'rniga reject(...), callback(null, narx) o'rniga resolve(narx). Error-first kelishuvining ikki yo'li endi ikki alohida funksiya.
3.2 Executor darhol, sinxron ishlaydi
Bir nozik joy. Executor keyinroq emas, new Promise chaqirilgan zahoti, sinxron bajariladi:
console.log("1");
const chek = new Promise((resolve) => {
console.log("2: executor ichida");
resolve("osh");
console.log("3: resolve'dan keyin ham davom etadi");
});
console.log("4");Konsolda:
1
2: executor ichida
3: resolve'dan keyin ham davom etadi
4Ikki xulosa:
- Executor ichidagi kod — oddiy sinxron kod. Asinxronlik u yerda faqat siz qo'ygan
setTimeout(yoki boshqa asinxron ish) tufayli paydo bo'ladi. resolvechaqirilishi funksiyadan chiqmaydi — u faqat Promise holatini o'zgartiradi. Shuning uchunnarxniSoradarejectdan keyinreturnqo'ydik: keyingi qatorlar bekorga bajarilmasin.
3.3 Executor ichidagi throw
Executor ichida xato tashlansa, Promise o'zi rad etiladi — dastur to'xtamaydi:
const chek = new Promise(() => {
throw new Error("Gaz o'chib qoldi");
});
chek.catch((xato) => {
console.log("Ushlandi:", xato.message);
});Konsolda:
Ushlandi: Gaz o'chib qoldiBu reject(new Error("Gaz o'chib qoldi")) bilan bir xil. Faqat bitta shart bor: throw executor'ning sinxron qismida bo'lishi kerak. Executor ichidagi setTimeout callback'ida throw qilsangiz — u allaqachon boshqa stekda, Promise uni ko'rmaydi va dastur to'xtaydi (Callbacklar darsidagi "try tugadi" holati). Asinxron joyda doim reject ni chaqiring.
catch ni hozir ko'rdingiz — uni batafsil keyingi bo'limda ko'ramiz.
3.4 Promise ishni boshqarmaydi — u ishni kuzatadi
Executor darhol ishlashidan muhim xulosa chiqadi: ish new Promise paytida boshlanadi. Hech kim then ulamasa ham, taymer baribir ishlaydi:
function oshDamla() {
return new Promise((resolve) => {
console.log("Rustam aka qozonni yoqdi");
setTimeout(() => resolve("osh"), 100);
});
}
const chek = oshDamla();
console.log("Hali hech kim natijani so'ramadi");Konsolda:
Rustam aka qozonni yoqdi
Hali hech kim natijani so'ramadithen yo'q, lekin qozon yondi. Promise — ishni boshqaradigan "pult" emas, ishning natijasi uchun chek, xolos. Bundan ikki amaliy qoida kelib chiqadi:
- Ishni keyinroq boshlamoqchi bo'lsangiz, Promise'ni emas, Promise qaytaradigan funksiyani saqlang:
oshDamla— hali ish emas,oshDamla()— ish boshlandi. - Promise'ning o'zida "to'xtat" tugmasi yo'q. Keraksiz bo'lib qolgan ishni bekor qilish uchun alohida vosita bor —
AbortController, shu qismda o'rganamiz.
Birinchi qoida keyingi darslarda juda muhim bo'ladi. Ketma-ket va parallel bajarish darsida aynan "ish qachon boshlanadi?" savoli kodni uch barobar tezlashtiradi.
Tekshirib ko'ring:
const a = oshDamla(); const b = oshDamla();— nechta qozon yonadi?
Javob
Ikkita. Har oshDamla() chaqiruvi yangi Promise yaratadi, har birining executor'i darhol ishlaydi va o'z taymerini qo'yadi. Ikkala ish bir vaqtda ketadi.
Tekshirib ko'ring: Executor
return 35000qilsa, Promise "bajarildi" holatiga o'tadimi?
Javob
Yo'q. Executor'ning qaytargan qiymati e'tiborsiz qoladi. Promise faqat resolve yoki reject chaqirilganda (yoki executor throw qilganda) hal bo'ladi. new Promise(() => { return 35000; }) abadiy "kutilmoqda" holatida qoladi.
4. Natijani olish: then, catch, finally
4.1 then — bajarilganda
Chek qo'limizda. Natija kelganda nima qilishni aytish uchun then metodi bor. Unga funksiya berasiz, Promise bajarilganda u qiymat bilan chaqiriladi:
function narxniSora(taom) {
return new Promise((resolve) => {
setTimeout(() => resolve(taom === "osh" ? 35000 : 30000), 200);
});
}
console.log("Oshxonadan so'raldi");
narxniSora("osh").then((narx) => {
console.log(`Osh: ${narx} so'm`);
});
console.log("Kutish davomida choy quyildi");Konsolda:
Oshxonadan so'raldi
Kutish davomida choy quyildi
Osh: 35000 so'mTashqaridan bu callback'ga o'xshaydi — u ham keyinroq chaqiriladi. Lekin farq katta. Callback'ni biz oshxonaga berardik. then ni esa o'z qo'limizdagi chekka ulaymiz. Oshxona bizning funksiyamizni umuman ko'rmaydi: u faqat resolve ni chaqiradi, xolos. Boshqaruv qaytib bizga keldi.
4.2 catch — rad etilganda
catch — Promise rad etilganda chaqiriladigan funksiyani ulaydi. Unga xato (rad etish sababi) beriladi:
const menyu = { osh: 35000, manti: 30000 };
function narxniSora(taom) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (!Object.hasOwn(menyu, taom)) {
reject(new Error(`Menyuda yo'q: ${taom}`));
return;
}
resolve(menyu[taom]);
}, 200);
});
}
narxniSora("palov")
.then((narx) => console.log(`Narx: ${narx} so'm`))
.catch((xato) => console.log("Xato:", xato.message));Konsolda:
Xato: Menyuda yo'q: palovPromise rad etildi — shuning uchun then dagi funksiya chaqirilmadi, catch dagisi chaqirildi. "palov" o'rniga "osh" yozsangiz — aksincha: Narx: 35000 so'm, catch jim.
Qatorlarning joylashuviga e'tibor bering: .then(...) va .catch(...) yangi qatorda, nuqta bilan boshlanadi. Bu bitta ifoda — narxniSora("palov").then(...).catch(...) — faqat o'qish uchun bo'lingan. Nega then dan keyin catch ni ulash mumkinligini Promise zanjiri darsida ko'ramiz.
then ning ikkinchi argumenti ham bor: chek.then(narxBilan, xatoBilan). U ham rad etishni ushlaydi. Lekin zamonaviy kodda catch ko'proq ishlatiladi — o'qish osonroq. Ikkalasining nozik farqini ham keyingi darsda ko'ramiz.
4.3 finally — har qanday holatda
finally — Promise qanday hal bo'lishidan qat'i nazar chaqiriladi. try / catch / finally dagi finally ning aynan o'zi. Odatda "tozalash" uchun: yuklanish belgisini yashirish, tugmani qayta yoqish.
function narxniSora(taom) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (taom === "osh") resolve(35000);
else reject(new Error(`Menyuda yo'q: ${taom}`));
}, 100);
});
}
console.log("Yuklanmoqda...");
narxniSora("palov")
.then((narx) => console.log(`Narx: ${narx} so'm`))
.catch((xato) => console.log("Xato:", xato.message))
.finally(() => console.log("Yuklanish belgisi yashirildi"));Konsolda:
Yuklanmoqda...
Xato: Menyuda yo'q: palov
Yuklanish belgisi yashirildifinally dagi funksiya argument olmaydi: u natijani ham, xatoni ham bilmaydi — bilishi shart ham emas. "osh" bilan sinasangiz ham, oxirgi qator baribir chiqadi.
Tekshirib ko'ring: Promise rad etildi, lekin sizda faqat
thenbor,catchyo'q.thendagi funksiya chaqiriladimi?
Javob
Yo'q. then ning (birinchi) funksiyasi faqat bajarilganda chaqiriladi. Rad etilgan Promise'da u jim o'tkazib yuboriladi. Xato esa hech kim ushlamagani uchun «ushlanmagan rad etilish» bo'ladi — buni «Ko'p uchraydigan xatolar» da ko'ramiz.
5. then qachon chaqiriladi: microtask
5.1 Qadamma-qadam
Event loop darsida "microtask'ning asosiy manbai — Promise" degan edik. Endi buni ko'ramiz. Qoida bitta: Promise hal bo'lganda uning then callback'lari microtask navbatiga qo'yiladi.
console.log("1. Buyurtma berildi");
const chek = new Promise((resolve) => {
setTimeout(() => resolve("osh"), 300);
});
chek.then((taom) => {
console.log(`3. Tayyor: ${taom}`);
});
console.log("2. Chek qo'lda");Konsolda:
1. Buyurtma berildi
2. Chek qo'lda
3. Tayyor: oshQadamma-qadam kuzating. O'ngda — chek ning holati va uchta navbat-joy. then callback'i qaysi navbatdan o'tishiga e'tibor bering:
Diqqat qiling: then callback'ni hech qayerga "jo'natmaydi". Chek kutilayotganda callback chekning ichida, ro'yxatda turadi. Faqat resolve chaqirilgan lahzada u microtask navbatiga o'tadi.
5.2 Allaqachon hal bo'lgan Promise
Agar then ni Promise hal bo'lgandan keyin ulasak-chi? Bu yerda executor resolve ni darhol, sinxron chaqiradi. Ko'pchilik "chek tayyor — demak then ham darhol ishlaydi" deb o'ylaydi va 1, 3, 2 ni kutadi. Sinab ko'ramiz:
const chek = new Promise((resolve) => resolve("osh"));
console.log("1");
chek.then((taom) => console.log("3:", taom));
console.log("2");Konsolda:
1
2
3: oshChek allaqachon bajarilgan bo'lsa ham, then callback'i sinxron kod tugagandan keyin chiqdi. Bu tasodif emas — standartning qat'iy qoidasi: then callback'i hech qachon sinxron chaqirilmaydi. U doim microtask navbatidan o'tadi.
Diqqat: Bu qoida yodda tursin: Promise'ning holati qanday bo'lishidan qat'i nazar,
then,catchvafinallycallback'lari joriy sinxron kod tugagach ishlaydi.
5.3 Kech qo'shilgan then ham natijani oladi
Hodisa tinglovchisi bilan solishtiring. Tugma bosilgandan keyin addEventListener qilsangiz, o'sha bosishni bilmaysiz — u o'tib ketgan. Promise esa natijani eslab qoladi. Bitta chekka istalgancha then ulash mumkin, istalgan paytda:
const chek = new Promise((resolve) => {
setTimeout(() => resolve("osh"), 100);
});
chek.then((taom) => console.log("Dilshod aka:", taom));
setTimeout(() => {
chek.then((taom) => console.log("Ofitsiant Otabek:", taom));
}, 300);Konsolda:
Dilshod aka: osh
Ofitsiant Otabek: oshOtabek chekka osh tayyor bo'lgandan 200 ms keyin qaradi — natija hamon o'sha yerda. Ikkalasi ham bitta natijani oldi, oshxona esa oshni bir marta tayyorladi.
Tekshirib ko'ring: Quyidagi kod nima chiqaradi va qaysi tartibda?
const c = new Promise((r) => r(1)); c.then(() => console.log("A")); console.log("B");
Javob
Avval B, keyin A. Promise darhol bajarildi, then uning callback'ini microtask navbatiga qo'ydi. Microtask esa sinxron kod (console.log("B")) tugagandan keyin ishlaydi.
6. Promise callback muammolarini qanday hal qiladi
6.1 Faqat bir marta
Callbacklar darsidagi to'lov kutubxonasi callback'ni ikki marta chaqirgan edi. Uni himoya qilish uchun birMarta o'ramini yozdik. Promise'da bu himoya ichida tayyor: birinchi resolve yoki reject dan keyingi hamma chaqiruvlar e'tiborsiz qoladi.
// Begona kutubxona — ichida hamon xato bor
function tolovQil(summa) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("to'landi"), 100);
setTimeout(() => resolve("to'landi"), 150);
setTimeout(() => reject(new Error("bekor")), 200);
});
}
let tushum = 0;
tolovQil(35000).then((holat) => {
tushum += 35000;
console.log(`To'lov: ${holat}, tushum: ${tushum} so'm`);
});Konsolda:
To'lov: to'landi, tushum: 35000 so'mKutubxona resolve ni ikki marta, keyin yana reject ni chaqirdi. Lekin Promise birinchi resolve da hal bo'ldi va "qotib" qoldi. Bizning then aynan bir marta ishladi — birMarta siz.
6.2 Doim asinxron
"Zalgo" muammosi — kesh bo'lsa callback sinxron, bo'lmasa asinxron chaqirilardi. Promise bilan bu ham o'z-o'zidan yo'qoladi. Keshdan olingan narx ham darhol bajarilgan Promise sifatida qaytadi, then esa — biz endigina ko'rdik — doim microtask'da ishlaydi:
const kesh = new Map();
function narxniOl(taom) {
if (kesh.has(taom)) {
return new Promise((resolve) => resolve(kesh.get(taom)));
}
return new Promise((resolve) => {
setTimeout(() => {
kesh.set(taom, 35000);
resolve(35000);
}, 100);
});
}
function sotibOl(nomi) {
console.log(`${nomi}: so'rov`);
narxniOl("osh").then((n) => console.log(`${nomi}: narx ${n}`));
console.log(`${nomi}: so'rovdan keyingi qator`);
}
sotibOl("1-mehmon");
setTimeout(sotibOl, 300, "2-mehmon");Konsolda:
1-mehmon: so'rov
1-mehmon: so'rovdan keyingi qator
1-mehmon: narx 35000
2-mehmon: so'rov
2-mehmon: so'rovdan keyingi qator
2-mehmon: narx 35000Ikkala mehmonda ham tartib bir xil. Callback'li versiyada ikkinchi mehmonda "narx" "keyingi qator" dan oldin chiqqan edi.
6.3 Xato — alohida yo'ldan
Error-first callback'da har safar if (xato) ni yozish kerak edi, unutsangiz — xato yutilardi. Promise'da xato alohida kanaldan keladi: catch ga. then dagi funksiya xatoni umuman ko'rmaydi, uni tekshirish shart emas.
Natijada uchta kafolat, va ularni tilning o'zi beradi:
| Callback muammosi | Promise'da |
|---|---|
| ikki marta chaqirish | faqat birinchi resolve/reject hisobga olinadi |
| goh sinxron, goh asinxron | then doim microtask'da |
| xatoni tekshirishni unutish | xato alohida — catch ga keladi |
Callback hell piramidasi-chi? Uni Promise zanjiri yechadi — keyingi darsning mavzusi.
Tekshirib ko'ring: Begona kutubxona Promise ichida avval
reject(new Error("bekor")), keyinresolve("to'landi")ni chaqirdi. Sizningthenishlaydimi yokicatch?
Javob
catch. Promise birinchi chaqiruvda — reject da — rad etildi va hal bo'ldi. Keyingi resolve e'tiborsiz qoladi: hal bo'lgan Promise o'zgarmaydi.
7. Ko'p uchraydigan xatolar
7.1 Ushlanmagan rad etilish
catch siz qolgan rad etilgan Promise — ushlanmagan rad etilish (unhandled rejection):
function narxniSora(taom) {
return new Promise((resolve, reject) => {
setTimeout(() => reject(new Error(`Menyuda yo'q: ${taom}`)), 100);
});
}
narxniSora("palov").then((narx) => console.log(narx));Node 24 da (fayl yo'li qisqartirildi):
file:///C:/.../11/rad.mjs:3
setTimeout(() => reject(new Error(`Menyuda yo'q: ${taom}`)), 100);
^
Error: Menyuda yo'q: palov
at Timeout._onTimeout (file:///C:/.../11/rad.mjs:3:29)
at listOnTimeout (node:internal/timers:685:17)
at process.processTimers (node:internal/timers:618:7)
Node.js v24.21.0Node 15 dan beri ushlanmagan rad etilish dasturni to'xtatadi — xuddi ushlanmagan throw kabi. Brauzer sahifani to'xtatmaydi, lekin konsolga qizil xabar chiqaradi: Uncaught (in promise) Error: Menyuda yo'q: palov — "ushlanmagan (Promise ichida) xato". Ikkala holatda ham xato e'tibordan chetda qoldi degani.
Agar reject ga Error emas, oddiy satr berilsa, Node boshqacha matn chiqaradi:
UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "palov yo'q".Tarjimasi: "Bu xato yo async funksiya ichida catch blokisiz throw qilishdan, yo .catch() bilan ushlanmagan Promise'ni rad etishdan kelib chiqdi. Promise «palov yo'q» sababi bilan rad etildi". Async funksiyalarni async / await darsida ko'ramiz. Xabarda stack trace ham yo'q — satrda u bo'lmaydi. Shuning uchun doim Error bilan rad eting.
Tuzatish: har Promise zanjirining oxirida catch bo'lsin. Global "oxirgi himoya chizig'i" ham bor — Ushlanmagan xatolar darsida.
7.2 resolve ni hech qachon chaqirmaslik
function stolTop(odam) {
return new Promise((resolve) => {
if (odam <= 20) {
setTimeout(() => resolve(5), 100);
}
// odam > 20 bo'lsa — hech narsa chaqirilmaydi!
});
}stolTop(25) abadiy "kutilmoqda" bo'lib qoladi: na then, na catch, na finally ishlaydi. Xato xabari ham yo'q — eng sezilmaydigan xato. Tuzatish: executor'dagi har yo'l resolve yoki reject bilan tugasin. if bo'lsa — else da reject.
7.3 then dan natijani tashqariga olib chiqish
let narx;
narxniSora("osh").then((n) => {
narx = n;
});
console.log(narx); // undefinedCallback'lardagi eski xato, yangi kiyimda. then callback'i sinxron koddan keyin ishlaydi — console.log paytida narx hali bo'sh. Tuzatish: natijaga bog'liq kod then ichida bo'lsin yoki uni keyingi then ga uzating (Promise zanjiri).
7.4 then ga funksiya o'rniga chaqiruv berish
chek.then(console.log("tayyor")) — console.log darhol chaqiriladi va undefined qaytaradi. then ga esa undefined beriladi va u jim e'tiborsiz qoldiriladi. Taymerlar darsidagi setTimeout(salomBer(), 1000) xatosining o'zi. Tuzatish: chek.then(() => console.log("tayyor")).
7.5 "Promise'ga o'rasam — og'ir ish asinxron bo'ladi"
Sardor oy oxiridagi og'ir hisobni sahifa qotmasin deb Promise'ga o'radi:
function hisobla() {
return new Promise((resolve) => {
let summa = 0;
for (let i = 0; i < 3_000_000_000; i++) summa += i % 100;
resolve(summa);
});
}Sahifa baribir qotadi. Sababini «Executor darhol, sinxron ishlaydi» bo'limida ko'rdik: sikl new Promise paytida, stekda bajariladi. Promise kutishni o'zi yaratmaydi — u faqat host bajaradigan kutishning (taymer, fayl, tarmoq) natijasini yetkazadi. Tuzatish: og'ir hisobni bo'laklarga bo'lish (Event loop darsidagi 3-mashq) yoki alohida thread'ga chiqarish (Web Workers, 13-qismda).
8. Mashqlar
1-mashq (oson): Bron Promise bilan
Callbacklar darsidagi stolniBronQil ni Promise qaytaradigan qilib qayta yozing. stolniBronQil(odam) 200 ms dan keyin: odam 1 dan 20 gacha bo'lsa — "<odam> kishilik stol bron qilindi" bilan bajarilsin, aks holda Error("Odam soni 1–20 oralig'ida bo'lsin") bilan rad etilsin. 3 va 0 bilan then/catch orqali sinang.
Yechim
function stolniBronQil(odam) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (odam < 1 || odam > 20) {
reject(new Error("Odam soni 1–20 oralig'ida bo'lsin"));
return;
}
resolve(`${odam} kishilik stol bron qilindi`);
}, 200);
});
}
stolniBronQil(3)
.then((xabar) => console.log(xabar))
.catch((xato) => console.log("Xato:", xato.message));
stolniBronQil(0)
.then((xabar) => console.log(xabar))
.catch((xato) => console.log("Xato:", xato.message));Konsolda:
3 kishilik stol bron qilindi
Xato: Odam soni 1–20 oralig'ida bo'lsinCallback'li versiyada natijaniYoz(xato, xabar) ichida if (xato) kerak edi. Bu yerda ikki yo'l ikki alohida funksiyada: then faqat muvaffaqiyatni, catch faqat xatoni ko'radi.
2-mashq (o'rta): Tartibni oldindan ayting
Avval qog'ozda har qatorga "S" (sinxron), "M" (microtask) yoki "T" (taymer task'i) deb belgi qo'ying, keyin chiqish tartibini yozing. Ishora: executor — sinxron; hal bo'lgan Promise'ning then callback'i — microtask.
console.log("A");
setTimeout(() => console.log("B"), 0);
const chek = new Promise((resolve) => {
console.log("C");
resolve();
});
chek.then(() => console.log("D"));
queueMicrotask(() => console.log("E"));
console.log("F");Yechim
A — S, B — T, C — S (executor), D — M, E — M, F — S.
Konsolda:
A
C
F
D
E
BSinxronlar kod tartibida: A, C (executor darhol ishlaydi), F. Keyin microtask navbati: D birinchi qo'yilgan (chek allaqachon bajarilgan edi, then callback'ni darhol navbatga qo'ydi), keyin E. Oxirida taymer task'i — B.
3-mashq (qiyin): Callback'li funksiyani Promise'ga o'rash
Node'ning readFile funksiyasi callback'li (Callbacklar darsida ko'rgansiz). kurs/mashqlar/11/05-promise/faylniOqi.mjs faylida faylniOqi(yol) funksiyasini yozing. U readFile(yol, "utf8", callback) ni chaqirsin va Promise qaytarsin: xato bo'lsa — rad etilsin (xatoning o'zi bilan), bo'lmasa — fayl matni bilan bajarilsin. Sinash: mavjud bo'lmagan "bronlar.json" ni o'qib, catch da xato.code ni chiqaring.
Yechim
import { readFile } from "node:fs";
function faylniOqi(yol) {
return new Promise((resolve, reject) => {
readFile(yol, "utf8", (xato, matn) => {
if (xato) {
reject(xato);
return;
}
resolve(matn);
});
});
}
faylniOqi("bronlar.json")
.then((matn) => console.log("Fayl uzunligi:", matn.length))
.catch((xato) => console.log("O'qib bo'lmadi:", xato.code))
.finally(() => console.log("Tugadi"));Konsolda:
O'qib bo'lmadi: ENOENT
TugadiBu — callback'li API'ni Promise'ga aylantirishning umumiy naqshi: executor ichida eski funksiyani chaqirasiz, error-first callback'ning ikki yo'lini reject va resolve ga ulaysiz. reject(xato) ga Node'ning o'z Error obyektini beryapmiz — unda code bor. Bu naqsh shunchalik ko'p uchraydiki, Node'da uning tayyor vositasi bor — Promise yordamchilari va promisify darsida.
Mavjud faylni ham sinang: faylniOqi(import.meta.filename) — fayl o'zini o'qiydi.
git add 11/05-promise/faylniOqi.mjs
git commit -m "11/05: readFile ni Promise'ga o'rash"9. Real ishda
- Har joyda Promise. Zamonaviy JavaScript'da kutish kerak bo'lgan deyarli hamma API Promise qaytaradi. Brauzerda: tarmoqdan ma'lumot olish (
fetchasoslari — 11-qismning ikkinchi yarmida, hozir bilish shart emas), clipboard, kamera,audio.play(). Node'da:node:fs/promises, ma'lumotlar bazasi drayverlari. - Kutubxonalar. To'lov tizimlari (Click, Payme SDK'lari), Telegram bot kutubxonalari, ORM'lar — hammasi Promise bilan ishlaydi. Callback'li eski API'lar ham Promise'ga o'raladi — 3-mashqdagidek.
- Sintaksis ustiga sintaksis. Kundalik kodda
theno'rniga ko'pinchaasync/awaityoziladi. Lekin u Promise'ning ustiga qurilgan: Promise'ni tushunmasdanawaitxatolarini topib bo'lmaydi. - Intervyu. "Promise'ning holatlari qanday?", "Executor qachon ishlaydi?", "
thencallback'i sinxronmi?", "Bu kod qaysi tartibda chiqaradi?" — juda ko'p so'raladi.
Xulosa
- Promise — kelajakdagi natija uchun obyekt: kutilmoqda → bajarildi yoki rad etildi. Hal bo'lgach o'zgarmaydi.
new Promise((resolve, reject) => ...)— executor darhol, sinxron ishlaydi; ish tugagandaresolve(qiymat)yokireject(xato)chaqiriladi.then— bajarilganda,catch— rad etilganda,finally— har qanday holatda (argumentsiz).thencallback'lari doim microtask navbati orqali, sinxron koddan keyin ishlaydi — Promise allaqachon hal bo'lgan bo'lsa ham.- Promise kafolatlari: faqat bir marta, doim asinxron, xato alohida kanalda.
- Rad etilgan Promise'ni doim
catchqiling va doimErrorbilan rad eting.
Keyingi dars: Promise zanjiri — then doim yangi Promise qaytaradi: callback hell piramidasi tekis zanjirga aylanadi, xato esa zanjir bo'ylab pastga, bitta catch gacha oqadi.
Manbalar
- ECMAScript spetsifikatsiyasi: "Promise Objects" — tc39.es/ecma262
- MDN: "Promise", "Using promises" — developer.mozilla.org
- Node.js hujjatlari: "--unhandled-rejections" (
throwrejimi, Node 15 dan standart) — nodejs.org - Jake Archibald, "JavaScript Promises: an introduction" — web.dev
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!