Mundarija (36)
- Bu darsda
- 1. Nega bu kerak?
- 2. Promise.resolve va Promise.reject
- 2.1 Tayyor qiymatdan Promise
- 2.2 Promise'ni qayta o'ramaydi
- 2.3 Tayyor xatodan Promise
- 3. kut(ms) — kutib turish
- 3.1 O'zimiz yozamiz
- 3.2 Node'ning tayyor varianti
- 4. Promisify: callback'ni Promise'ga o'rash
- 4.1 Naqsh
- 4.2 Umumiy promisifyQil
- 4.3 Node'da tayyor: util.promisify
- 4.4 this tuzog'i
- 4.5 Promisify qachon yaramaydi
- 5. Promise.withResolvers: tashqaridan hal qilish
- 5.1 Muammo: resolve ichkarida qamalgan
- 5.2 Yangi usul
- 5.3 Buyurtmalar navbati
- 6. Promise.try: sinxron xatoni ham ushlash
- 6.1 Muammo: ikki xil xato
- 6.2 Yechim
- 6.3 fn qachon ishlaydi?
- 6.4 async funksiya bilan solishtirish
- 7. Ko'p uchraydigan xatolar
- 7.1 Tayyor Promise'ni new Promise ga o'rash
- 7.2 kut ni await siz chaqirish
- 7.3 Metodni bind siz promisify qilish
- 7.4 Yangi metodni tekshirmasdan ishlatish
- 8. Mashqlar
- 1-mashq (oson): Bosqichli tayyorlash
- 2-mashq (o'rta): Eski bronni promisify qiling
- 3-mashq (qiyin): Hodisani muddat bilan kutish
- 9. Real ishda
- Xulosa
- Manbalar
Promise yordamchilari: Promise.resolve, withResolvers, Promise.try va promisify
Qisqacha: Har Promise uchun
new Promise(...)yozish shart emas. Tayyor qiymatdan Promise —Promise.resolve(qiymat), tayyor xatodan —Promise.reject(xato). Callback'li funksiyani Promise'ga Node'dautil.promisify(fn)o'raydi. Promise'ni tashqaridan, keyinroq hal qilish kerak bo'lsa —Promise.withResolvers()(ES2024). Funksiya sinxron xato tashlashi ham, Promise qaytarishi ham mumkin bo'lsa —Promise.try(fn)(ES2025) ikkalasini bittacatchga yo'naltiradi.
Bu darsda
Promise.resolvevaPromise.rejectbilan tayyor Promise yasaysiz va ular qachon kerakligini bilasiz.kut(ms)— "uxlab turish" funksiyasi qanday ishlashini oxirigacha tushunasiz va Node'ning tayyor variantini ishlatasiz.- Callback'li funksiyalarni
util.promisifybilan va qo'lda Promise'ga o'raysiz,thistuzog'ini chetlab o'tasiz. Promise.withResolversbilan Promise'ni tashqaridan hal qilasiz: navbat va hodisani kutish naqshlari.Promise.trysinxron xatoni ham Promise zanjiriga qanday olib kirishini tushuntira olasiz.
Oldin bilishingiz kerak: Promise asoslari, async / await, Promise kombinatorlari, Callbacklar va callback hell.
1. Nega bu kerak?
O'tgan darslarda har Promise'ni new Promise((resolve, reject) => ...) bilan yasadik. Bu konstruktor — eng umumiy vosita. Lekin kundalik kodda to'rtta vaziyat qayta-qayta uchraydi va har biriga new Promise yozish noqulay:
| Vaziyat | Tayyor vosita |
|---|---|
| Natija allaqachon bor (kesh), lekin funksiya Promise qaytarishi kerak | Promise.resolve |
Eski callback'li funksiyani await bilan ishlatmoqchisiz |
util.promisify |
| Promise'ni bir joyda yaratib, boshqa joyda hal qilish kerak | Promise.withResolvers |
| Funksiya sinxron xato tashlashi ham mumkin | Promise.try |
Bugungi dars — shu "asboblar qutisi". Har asbob kichik, lekin real kodda ularni har kuni ko'rasiz. Xuddi oshxonadagi pichoq kabi: bitta katta pichoq bilan hamma narsani kesish mumkin, lekin non uchun alohida, sabzi uchun alohida pichoq ishni tezlashtiradi.
2. Promise.resolve va Promise.reject
2.1 Tayyor qiymatdan Promise
Promise asoslari darsida keshli narxniOl shunday yozilgan edi:
if (kesh.has(taom)) {
return new Promise((resolve) => resolve(kesh.get(taom)));
}Uning qisqa shakli — Promise.resolve(qiymat): berilgan qiymat bilan darhol bajarilgan Promise. Ma'nosi aynan bir xil:
const kesh = new Map([["osh", 35000]]);
function narxniOl(taom) {
if (kesh.has(taom)) {
return Promise.resolve(kesh.get(taom));
}
return new Promise((resolve) => {
setTimeout(() => {
kesh.set(taom, 28000);
resolve(28000);
}, 100);
});
}
console.log("1. So'rovlar yuborildi");
narxniOl("osh").then((n) => console.log("3. Osh:", n));
narxniOl("lag'mon").then((n) => console.log("4. Lag'mon:", n));
console.log("2. Sinxron kod tugadi");Konsolda:
1. So'rovlar yuborildi
2. Sinxron kod tugadi
3. Osh: 35000
4. Lag'mon: 28000Osh keshda bor, lekin uning narxi ham sinxron koddan keyin chiqdi. Promise.resolve qaytargan Promise allaqachon bajarilgan, then esa doim microtask orqali ishlaydi. Funksiya natijasi qayerdan kelishidan qat'i nazar, bir xil shaklda va bir xil tartibda keladi.
2.2 Promise'ni qayta o'ramaydi
Promise.resolve ga Promise bersangiz-chi? U yangi Promise yasamaydi — o'shaning o'zini qaytaradi:
const chek = new Promise((resolve) => {
setTimeout(resolve, 100, "osh");
});
console.log(Promise.resolve(chek) === chek); // trueShuning uchun Promise.resolve(x) — "x Promise bo'lsa ham, bo'lmasa ham, Promise qil" degani. Kombinatorlar (Promise kombinatorlari) ham massivdagi har elementni shunday o'raydi — Promise.all([35000, chek]) shuning uchun ishlaydi. O'tgan darsdagi 3-mashqda hammasi funksiyasi aynan shu ishni qilgan edi.
Yana bir nozik detal: Promise.resolve then metodi bor har qanday obyektni Promise deb qabul qiladi. Bunday obyekt thenable ("then'i bor") deyiladi:
const thenable = {
then(resolve) {
resolve("osh");
},
};
Promise.resolve(thenable).then((t) => console.log(t)); // oshOddiy obyekt, lekin unda then metodi bor. Promise.resolve uni chaqirdi, resolve("osh") esa haqiqiy Promise'ni bajardi. Eski kutubxonalarning (masalan, jQuery) Promise'ga o'xshash obyektlari shu yo'l bilan haqiqiy Promise'ga aylanadi. await thenable ham xuddi shunday ishlaydi.
2.3 Tayyor xatodan Promise
Promise.reject(xato) — berilgan sabab bilan darhol rad etilgan Promise. Ko'pincha funksiya boshidagi tekshiruvda ishlatiladi: noto'g'ri argument — kutishning ma'nosi yo'q.
function stolniBronQil(odam) {
if (odam < 1 || odam > 20) {
const xato = new Error("Odam soni 1–20 oralig'ida bo'lsin");
return Promise.reject(xato);
}
return new Promise((resolve) => {
setTimeout(resolve, 200, `${odam} kishilik stol bron qilindi`);
});
}
stolniBronQil(0)
.then((xabar) => console.log(xabar))
.catch((xato) => console.log("Xato:", xato.message));Konsolda:
Xato: Odam soni 1–20 oralig'ida bo'lsinNega oddiy throw emas? Chunki funksiya Promise qaytaradi deb va'da bergan. Chaqiruvchi xatoni .catch da kutadi. throw bo'lsa, xato sinxron otilib, .catch gacha yetmasdi — chaqiruvchiga yana try/catch kerak bo'lardi.
async funksiya ichida esa bu muammo yo'q: u yerdagi throw o'zi rad etilgan Promise'ga aylanadi (async / await). Shuning uchun Promise.reject ko'proq async bo'lmagan funksiyalarda uchraydi.
Tekshirib ko'ring:
Promise.resolve(35000).then((n) => console.log(n)); console.log("salom");— qaysi biri birinchi chiqadi?
Javob
Avval salom, keyin 35000. Promise darhol bajarilgan bo'lsa ham, then callback'i microtask navbatiga tushadi va sinxron kod tugagach ishlaydi.
3. kut(ms) — kutib turish
3.1 O'zimiz yozamiz
kut ni Promise zanjiri darsidan beri ishlatib kelyapmiz. Endi uni yordamchilar qatorida to'liq ko'rib chiqamiz. Ko'p tillarda sleep(ms) degan buyruq bor: "shuncha vaqt kut". JavaScript'da bunday sinxron buyruq yo'q — u stekni bloklagan bo'lardi (Sinxron va asinxron kod). Lekin Promise va setTimeout bilan bir qatorda yasaladi:
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function sanoq() {
for (const son of [3, 2, 1]) {
console.log(son);
await kut(200);
}
console.log("Osh dasturxonda!");
}
sanoq();Konsolda:
3
2
1
Osh dasturxonda!Har await kut(200) da sanoq 200 ms to'xtaydi, lekin stek bo'sh: shu orada boshqa kod bemalol ishlaydi. Bu bloklovchi kutish emas — funksiya o'zini "pauza" qiladi.
Dasturchilar bu funksiyani sleep, delay yoki wait deb atashadi. Kursda — kut. U real ishda qayta urinishlar orasida kutish uchun (Asinxron naqshlar), animatsiya qadamlari va testlarda kerak bo'ladi.
3.2 Node'ning tayyor varianti
Node'da kut ni yozish shart emas — node:timers/promises modulida setTimeout ning Promise varianti bor:
import { setTimeout as kut } from "node:timers/promises";
const natija = await kut(200, "choy damlandi");
console.log(natija); // choy damlandiIkkinchi argument — Promise bajarilganda beriladigan qiymat. import { setTimeout as kut } — import nomini o'zgartirish (ESM import): aks holda u global setTimeout bilan to'qnashardi. Bu yerda await funksiya ichida emas, modulning eng yuqorisida turibdi — Node .mjs faylda bunga ruxsat beradi. Uni Dinamik import() va top-level await darsida to'liq ko'ramiz.
Brauzerda bunday modul yo'q — u yerda o'zimizning kut ni ishlatamiz.
4. Promisify: callback'ni Promise'ga o'rash
4.1 Naqsh
Promisify ("Promise'ga aylantirish") — error-first callback'li funksiyani Promise qaytaradigan funksiyaga o'rash. Promise asoslari darsining 3-mashqida readFile ni qo'lda o'ragan edingiz. Naqsh doim bir xil:
flowchart LR
C["Eski funksiya:<br/>fn(...args, callback)"] --> W["new Promise ichida<br/>chaqiriladi"]
W --> E{"callback(xato, natija)"}
E -- "xato bor" --> R["reject(xato)"]
E -- "xato = null" --> S["resolve(natija)"]Callback'ning ikki yo'li Promise'ning ikki yo'liga ulanadi. Har funksiya uchun buni qayta yozmaslik uchun umumiy yordamchi yasaymiz.
4.2 Umumiy promisifyQil
Callbacklar darsidagi narxniSora ni olamiz. Yordamchi istalgan error-first funksiyani o'raydi:
const menyu = { osh: 35000, manti: 30000 };
function narxniSora(taom, callback) {
setTimeout(() => {
if (!Object.hasOwn(menyu, taom)) {
callback(new Error(`Menyuda yo'q: ${taom}`));
return;
}
callback(null, menyu[taom]);
}, 100);
}
function promisifyQil(fn) {
return (...argumentlar) => {
return new Promise((resolve, reject) => {
fn(...argumentlar, (xato, natija) => {
if (xato) {
reject(xato);
return;
}
resolve(natija);
});
});
};
}
const narxniSoraP = promisifyQil(narxniSora);
async function narxlar() {
console.log("Osh:", await narxniSoraP("osh"));
try {
await narxniSoraP("palov");
} catch (xato) {
console.log("Xato:", xato.message);
}
}
narxlar();Konsolda:
Osh: 35000
Xato: Menyuda yo'q: palovQatorma-qator:
promisifyQil(fn)— funksiya qaytaradigan funksiya (Funksiya — qiymat: callback va HOF).fnclosure'da eslab qolinadi.(...argumentlar)— rest parametr:narxniSoraP("osh")chaqirilgandaargumentlar = ["osh"].fn(...argumentlar, callback)— asl funksiya o'z argumentlari va oxirida bizning callback bilan chaqiriladi. Error-first kelishuvida callback doim oxirgi parametr (Callbacklar).- Callback ichida — xato bo'lsa
reject, aks holdaresolve.
P qo'shimchasi — "Promise varianti" degan belgi; real kodda ham readFileP, queryAsync kabi nomlar uchraydi.
4.3 Node'da tayyor: util.promisify
Node'da bu yordamchi standart kutubxonada bor — util.promisify:
import { promisify } from "node:util";
import { readFile } from "node:fs";
const faylniOqi = promisify(readFile);
try {
await faylniOqi("bronlar.json", "utf8");
} catch (xato) {
console.log("O'qib bo'lmadi:", xato.code); // O'qib bo'lmadi: ENOENT
}bronlar.json yo'q — shuning uchun ENOENT ("bunday fayl yo'q", Callbacklar darsidan). util.promisify biznikidan aqlliroq: ba'zi funksiyalarning maxsus Promise varianti bor va u shuni topadi. Masalan, promisify(setTimeout) ham to'g'ri ishlaydi, garchi setTimeout da callback birinchi parametr bo'lsa ham.
Lekin Node'ning o'z fayl funksiyalari uchun promisify ham shart emas: tayyor Promise variantlari bor — node:fs/promises. Yangi kodda shuni ishlating:
import { readFile } from "node:fs/promises";
try {
await readFile("bronlar.json", "utf8");
} catch (xato) {
console.log("O'qib bo'lmadi:", xato.code); // O'qib bo'lmadi: ENOENT
}Qoida: avval tayyor Promise API'ni qidiring (fs/promises, timers/promises, dns/promises). Topilmasa — util.promisify. U ham yaramasa (masalan, brauzerda) — qo'lda o'rang.
4.4 this tuzog'i
Metodni promisify qilganda this yo'qoladi — xuddi metodni callback sifatida berganda yo'qolgani kabi (this yo'qolishi va uni tiklash):
import { promisify } from "node:util";
class Kassa {
constructor(nomi) {
this.nomi = nomi;
}
chekYoz(summa, callback) {
const kassa = this.nomi;
setTimeout(() => callback(null, `${kassa}: ${summa} so'm`), 100);
}
}
const kassa = new Kassa("1-kassa");
const xatoli = promisify(kassa.chekYoz);
try {
await xatoli(35000);
} catch (xato) {
console.log("Xato:", xato.message);
}
const togri = promisify(kassa.chekYoz.bind(kassa));
console.log(await togri(35000));Konsolda:
Xato: Cannot read properties of undefined (reading 'nomi')
1-kassa: 35000 so'mkassa.chekYoz — obyektdan uzib olingan funksiya. Promisify uni oddiy funksiya sifatida chaqiradi, this esa modulda undefined. Xabar: "undefined ning 'nomi' xususiyatini o'qib bo'lmadi". Tuzatish — bind(kassa): this ni oldindan bog'lash.
E'tibor bering: chekYoz ichidagi sinxron TypeError ham Promise'ning rad etilishiga aylandi. util.promisify asl funksiyani Promise ichida chaqiradi — ichidagi xato ham Promise yo'lidan keladi.
4.5 Promisify qachon yaramaydi
Promise bir marta hal bo'ladi. Shuning uchun promisify faqat bir martalik natija beradigan funksiyalarga mos:
setIntervalyoki hodisa tinglovchisi callback'ni ko'p marta chaqiradi — Promise faqat birinchisini oladi, qolganlari yo'qoladi. Ko'p marta keladigan ma'lumot uchun boshqa vosita bor — Asinxron iteratsiya.- Error-first bo'lmagan callback (
callback(natija)— xatosiz) —promisifyQilnatijani xato deb o'ylaydi varejectqiladi. Bunday funksiyani qo'lda o'rang.
Tekshirib ko'ring:
promisifyQilbilan o'ralgan funksiya ichidagi callback ikki marta chaqirilsa nima bo'ladi?
Javob
Hech narsa buzilmaydi: birinchi chaqiruv Promise'ni hal qiladi, ikkinchisidagi resolve yoki reject e'tiborsiz qoladi. Promise'ning "bir marta hal bo'lish" qoidasi callback'lardagi ikki marta chaqirish muammosini o'z-o'zidan hal qiladi.
5. Promise.withResolvers: tashqaridan hal qilish
5.1 Muammo: resolve ichkarida qamalgan
new Promise((resolve, reject) => ...) da resolve va reject faqat executor ichida mavjud. Ko'pincha esa Promise'ni hozir yaratish, lekin boshqa joyda, keyinroq hal qilish kerak bo'ladi.
«Bahor» oshxonasida: ofitsiant buyurtma beradi va chek oladi (Promise). Oshpaz esa taom tayyor bo'lganda alohida tugmani bosadi. Chekni yaratgan kod va uni hal qiladigan kod — ikki xil joyda.
Yillar davomida dasturchilar buni shunday aylanib o'tishgan:
let tayyorQil;
const chek = new Promise((resolve) => {
tayyorQil = resolve;
});
chek.then((taom) => console.log("Olib chiqildi:", taom));
setTimeout(() => tayyorQil("osh"), 100);Konsolda:
Olib chiqildi: oshresolve ni tashqi o'zgaruvchiga "olib chiqdik". Ishlaydi, lekin noqulay: let, executor, qo'shimcha o'zgaruvchilar. Bu naqsh deferred ("kechiktirilgan") deb ataladi va eski kutubxonalarda tez-tez uchraydi.
5.2 Yangi usul
Promise.withResolvers() — Promise va uning ikki "tugmasi"ni bitta obyektda qaytaradi:
const { promise, resolve, reject } = Promise.withResolvers();
promise.then((taom) => console.log("Olib chiqildi:", taom));
setTimeout(() => resolve("osh"), 100);Konsolda:
Olib chiqildi: osh{ promise, resolve, reject } — destructuring: obyektdan uchta xususiyatni bir qatorda olish. Kod qisqardi va maqsad aniq: "menga Promise va uni boshqarish tugmalari kerak".
Promise.withResolvers ES2024 da qo'shilgan. Baseline ma'lumotiga ko'ra 2024-yil martidan hamma asosiy brauzerda bor (Chrome 119, Firefox 121, Safari 17.4), 2026-yil sentyabridan esa "keng tarqalgan" (widely available). Node'da 22-versiyadan bor.
5.3 Buyurtmalar navbati
Endi to'liq misol. Ofitsiant buyurtmaBer bilan Promise oladi, oshpaz esa oshpazAytdi bilan uni hal qiladi. Ular faqat kutilayotgan Mapi orqali bog'langan:
const kutilayotgan = new Map();
function buyurtmaBer(taom) {
const { promise, resolve } = Promise.withResolvers();
kutilayotgan.set(taom, resolve);
console.log("Buyurtma:", taom);
return promise;
}
function oshpazAytdi(taom) {
const resolve = kutilayotgan.get(taom);
if (resolve) {
kutilayotgan.delete(taom);
resolve(`${taom} tayyor`);
}
}
buyurtmaBer("osh").then((xabar) => console.log(xabar));
buyurtmaBer("manti").then((xabar) => console.log(xabar));
setTimeout(() => oshpazAytdi("manti"), 100);
setTimeout(() => oshpazAytdi("osh"), 200);Konsolda:
Buyurtma: osh
Buyurtma: manti
manti tayyor
osh tayyorbuyurtmaBer hech qanday taymer qo'ymaydi va oshxona haqida hech narsa bilmaydi. U faqat va'da beradi va "tugma"ni navbatga qo'yadi. Promise kim tomonidan va qachon hal qilinishini oshpazAytdi belgilaydi.
Real kodda bu naqsh ko'p joyda: WebSocket orqali yuborilgan so'rovga javob kelishini kutish (WebSocket va Server-Sent Events), boshqa oynadan xabar kutish, test kutubxonalarida "shu hodisa bo'lguncha kut".
Tekshirib ko'ring: Yuqoridagi kodda
oshpazAytdi("lag'mon")chaqirilsa nima bo'ladi?
Javob
Hech narsa. kutilayotgan da lag'mon kaliti yo'q — get undefined qaytaradi va if (resolve) sharti bajarilmaydi. Bu tekshiruv bo'lmasa, undefined(...) chaqirilib, TypeError: resolve is not a function chiqardi.
6. Promise.try: sinxron xatoni ham ushlash
6.1 Muammo: ikki xil xato
Funksiya Promise qaytaradi deb o'ylaymiz va xatoni .catch bilan kutamiz. Lekin funksiya Promise qaytarishdan oldin, sinxron xato tashlasa-chi?
function menyuniOqi(matn) {
const menyu = JSON.parse(matn);
return Promise.resolve(menyu);
}
try {
menyuniOqi("{buzuq").catch((x) => console.log("catch:", x.name));
} catch (xato) {
console.log("try/catch ushladi:", xato.name);
}Konsolda:
try/catch ushladi: SyntaxErrorJSON.parse buzuq matnda sinxron SyntaxError tashladi (JSON). Funksiya Promise qaytarishga ulgurmadi — .catch gacha hech narsa yetmadi. Xatoni faqat tashqi try/catch ushladi. Demak bunday funksiyani chaqirgan kodga ikki himoya kerak: try/catch va .catch. Biri unutilsa — xato o'tib ketadi.
6.2 Yechim
Promise.try(fn, ...argumentlar) — fn ni chaqiradi va natijasini doim Promise'ga aylantiradi:
fnqiymat qaytarsa — o'sha qiymat bilan bajarilgan Promise;fnPromise qaytarsa — o'sha Promise;fnsinxron xato tashlasa — o'sha xato bilan rad etilgan Promise.
function menyuniOqi(matn) {
const menyu = JSON.parse(matn);
return Promise.resolve(menyu);
}
Promise.try(menyuniOqi, "{buzuq")
.then((menyu) => console.log("Menyu:", menyu))
.catch((xato) => console.log("catch ushladi:", xato.name));
Promise.try(menyuniOqi, '{"osh":35000}')
.then((menyu) => console.log("Menyu:", menyu));Konsolda:
catch ushladi: SyntaxError
Menyu: { osh: 35000 }Endi bitta .catch ikkala turdagi xatoni ham ushlaydi. Promise.try ning ikkinchi va keyingi argumentlari fn ga uzatiladi.
6.3 fn qachon ishlaydi?
Muhim farq: Promise.try fn ni darhol, sinxron chaqiradi. Shunga o'xshash eski usul — Promise.resolve().then(fn) — esa fn ni microtask'ga qoldiradi. Tartibni solishtiring:
console.log("1. boshlandi");
Promise.resolve().then(() => console.log("4. then ichida"));
Promise.try(() => console.log("2. Promise.try ichida"));
console.log("3. tugadi");Konsolda:
1. boshlandi
2. Promise.try ichida
3. tugadi
4. then ichidaQadamma-qadam qarang — then callback'i microtask navbatida kutadi, Promise.try ning funksiyasi esa navbatsiz, shu zahoti ishlaydi:
Nega bu muhim? Funksiya tez ishlashi kerak bo'lsa (masalan, foydalanuvchi bosishiga javob), uni bekorga keyinga surish kerak emas. Promise.try — "hozir chaqir, lekin natijani va xatoni Promise qilib ber".
6.4 async funksiya bilan solishtirish
async funksiya ham ichidagi throw ni rad etilgan Promise'ga aylantiradi. Shuning uchun Promise.try(fn) ni shunday ham yozish mumkin edi:
const natija = (async () => fn())();Bu — darhol chaqiriladigan async arrow funksiya. Ishlaydi, lekin o'qish qiyin. Promise.try xuddi shu ishni nomi bilan aytadi.
Promise.try ES2025 da qo'shilgan — eng yangi yordamchi. Baseline ma'lumotiga ko'ra 2025-yil yanvaridan hamma asosiy brauzerda bor (Chrome 128, Firefox 134, Safari 18.2), lekin hali "keng tarqalgan" emas. Node'da 24-versiyada bor, 22-versiyada esa yo'q — Node 22 da typeof Promise.try "undefined" beradi. Eski brauzer yoki Node'ni qo'llab-quvvatlash kerak bo'lsa — async arrow varianti.
Tekshirib ko'ring:
Promise.resolve(menyuniOqi("{buzuq"))yozilsa, xato.catchga tushadimi?
Javob
Yo'q. Avval argument hisoblanadi: menyuniOqi("{buzuq") chaqiriladi va sinxron SyntaxError tashlaydi — Promise.resolve umuman chaqirilmaydi. Promise.try(menyuniOqi, "{buzuq") da esa funksiyani Promise.try ning o'zi chaqiradi va xatoni ushlab, Promise'ga aylantiradi.
7. Ko'p uchraydigan xatolar
7.1 Tayyor Promise'ni new Promise ga o'rash
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function narxniOl() {
return new Promise((resolve) => {
kut(100).then(() => resolve(35000));
});
}
narxniOl().then((narx) => console.log(narx)); // 35000Ishlaydi, lekin ortiqcha. kut(100) allaqachon Promise — uni yana new Promise ga o'rashning hojati yo'q. Bu naqsh explicit construction anti-pattern ("ortiqcha konstruktor") deb ataladi. Uning xavfi: ichki Promise rad etilsa, tashqi Promise hech qachon hal bo'lmaydi — reject ga hech kim ulanmagan. To'g'risi — Promise'ni qaytarish yoki zanjir qilish:
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function narxniOl() {
return kut(100).then(() => 35000);
}
narxniOl().then((narx) => console.log(narx)); // 35000Qoida: new Promise faqat callback'li yoki hodisali API'ni o'rash uchun. Promise allaqachon bor bo'lsa — then, await yoki return.
7.2 kut ni await siz chaqirish
kut(1000); — hech narsani kutmaydi. U Promise qaytaradi va keyingi qator darhol bajariladi. Kutish faqat await kut(1000) yoki kut(1000).then(...) bilan bo'ladi. Bu async / await darsidagi "suzib yurgan Promise" xatosining o'zi.
7.3 Metodni bind siz promisify qilish
promisify(obyekt.metod) — this yo'qoladi va Cannot read properties of undefined chiqadi. Tuzatish: promisify(obyekt.metod.bind(obyekt)). Undan ham yaxshisi — kutubxonaning tayyor Promise API'sini qidiring.
7.4 Yangi metodni tekshirmasdan ishlatish
Promise.try Node 22 da yo'q: TypeError: Promise.try is not a function — "Promise.try funksiya emas". Xabar g'alati tuyuladi: aslida xususiyat undefined, uni chaqirib bo'lmaydi. Yangi imkoniyatni ishlatishdan oldin loyihangiz qaysi Node va qaysi brauzerlarda ishlashini tekshiring. Bu haqda JS versiyalari va brauzer mosligi darsida batafsil.
8. Mashqlar
1-mashq (oson): Bosqichli tayyorlash
kut(ms) funksiyasini yozing va u bilan choyDamla() async funksiyasini tuzing. U "Suv qaynayapti" deb yozsin, 300 ms kutsin, "Choy solindi" deb yozsin, 200 ms kutsin va "Choy tayyor" deb yozsin. Boshida va oxirida console.log bilan funksiyadan tashqarida "Mehmon kutyapti" deb ham yozing — u qaysi o'rinda chiqishini oldindan ayting.
Yechim
function kut(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function choyDamla() {
console.log("Suv qaynayapti");
await kut(300);
console.log("Choy solindi");
await kut(200);
console.log("Choy tayyor");
}
choyDamla();
console.log("Mehmon kutyapti");Konsolda:
Suv qaynayapti
Mehmon kutyapti
Choy solindi
Choy tayyorchoyDamla birinchi await gacha sinxron ishlaydi — "Suv qaynayapti" birinchi. await kut(300) da funksiya to'xtaydi va boshqaruv chaqiruvchiga qaytadi — "Mehmon kutyapti". Qolgani taymerlardan keyin.
2-mashq (o'rta): Eski bronni promisify qiling
Callbacklar darsining 1-mashqidagi stolniBronQil(odam, callback) error-first funksiyasini o'zgartirmasdan oling. promisifyQil bilan o'rang va Promise.allSettled (Promise kombinatorlari) bilan uchta bronni parallel bajaring: 3, 0 va 25 kishilik. Har natijani " ..." yoki " ..." deb chiqaring.
Yechim
function stolniBronQil(odam, callback) {
setTimeout(() => {
if (odam < 1 || odam > 20) {
callback(new Error("Odam soni 1–20 oralig'ida bo'lsin"));
return;
}
callback(null, `${odam} kishilik stol bron qilindi`);
}, 200);
}
function promisifyQil(fn) {
return (...argumentlar) => new Promise((resolve, reject) => {
fn(...argumentlar, (xato, natija) => {
if (xato) {
reject(xato);
return;
}
resolve(natija);
});
});
}
const bronQilP = promisifyQil(stolniBronQil);
async function bronlar() {
const natijalar = await Promise.allSettled(
[3, 0, 25].map((odam) => bronQilP(odam)),
);
for (const n of natijalar) {
if (n.status === "fulfilled") {
console.log("✅", n.value);
} else {
console.log("❌", n.reason.message);
}
}
}
bronlar();Konsolda:
✅ 3 kishilik stol bron qilindi
❌ Odam soni 1–20 oralig'ida bo'lsin
❌ Odam soni 1–20 oralig'ida bo'lsinEski funksiyaga bir harf ham tegmadik — promisifyQil uni tashqaridan o'radi. map uchta Promise yasaydi va ular parallel ishlaydi: umumiy vaqt — taxminan 200 ms. promisifyQil bu safar qisqaroq yozilgan: arrow funksiya new Promise(...) ni to'g'ridan-to'g'ri qaytaradi.
3-mashq (qiyin): Hodisani muddat bilan kutish
hodisaniKut(manba, nom, ms) funksiyasini yozing. U Promise qaytarsin:
manba(EventTarget) danomhodisasi sodir bo'lsa — hodisa obyekti bilan bajarilsin;msichida sodir bo'lmasa —`${nom} hodisasi ${ms} ms da kelmadi`xatosi bilan rad etilsin;- ikkala holatda ham "chiqindi" qolmasin: tinglovchi olib tashlansin, taymer tozalansin.
Promise.withResolvers ishlating. EventTarget, Event va { once: true } — 09-qismdan (Custom events va EventTarget, Listener opsiyalari); Node 24 da ular global. Faylni kurs/mashqlar/11/10-yordamchilar/hodisaniKut.mjs ga saqlang.
Yechim
function hodisaniKut(manba, nom, ms) {
const { promise, resolve, reject } = Promise.withResolvers();
function tinglovchi(event) {
clearTimeout(taymer);
resolve(event);
}
const taymer = setTimeout(() => {
manba.removeEventListener(nom, tinglovchi);
reject(new Error(`${nom} hodisasi ${ms} ms da kelmadi`));
}, ms);
manba.addEventListener(nom, tinglovchi, { once: true });
return promise;
}
const oshxona = new EventTarget();
setTimeout(() => oshxona.dispatchEvent(new Event("osh-tayyor")), 100);
async function kuzat() {
const event = await hodisaniKut(oshxona, "osh-tayyor", 300);
console.log("Keldi:", event.type);
try {
await hodisaniKut(oshxona, "manti-tayyor", 200);
} catch (xato) {
console.log("Xato:", xato.message);
}
}
kuzat();Konsolda:
Keldi: osh-tayyor
Xato: manti-tayyor hodisasi 200 ms da kelmadiKalit joylar:
- Hodisa keldi →
{ once: true }tinglovchini o'zi olib tashlaydi, biz taymerni tozalaymiz. - Muddat tugadi → tinglovchini biz olib tashlaymiz. Aks holda u kech kelgan hodisada
resolveni chaqirardi — zarari yo'q, lekin xotirada qolardi. tinglovchiichidataymerishlatilgan, garchi u pastroqda e'lon qilingan bo'lsa ham. Bu xato emas:tinglovchifaqat hodisa kelganda chaqiriladi, o'shandataymerallaqachon tayyor (TDZ).
Node'da bu funksiyaning tayyor varianti bor: events.once(manba, nom) (node:events modulidan). Muddatni esa AbortSignal.timeout bilan berish mumkin — Bekor qilish: AbortController darsida.
git add 11/10-yordamchilar/hodisaniKut.mjs
git commit -m "11/10: hodisaniKut — withResolvers va muddat"9. Real ishda
- Node migratsiyasi. Eski Node loyihalarida callback'li kod ko'p. Ularni bosqichma-bosqich
async/awaitga o'tkazishdautil.promisifybirinchi qadam bo'ladi. Yangi kodda —node:fs/promiseskabi tayyor variantlar. - Testlar. "Shu hodisa bo'lguncha kut", "100 ms kut va tekshir" — test kodida
kut(ms)vawithResolversdoimiy mehmon. Testlarni 12-qismda (Birinchi avtomatik test) yozishni boshlaymiz. - Kutubxona ichida. WebSocket klientlari, navbat kutubxonalari, "debounce" qiladigan funksiyalar — ichida
withResolversyoki deferred naqsh bor. - Kod sharhi. "Bu
new Promisenega kerak? Ichida allaqachon Promise bor-ku" — explicit construction anti-pattern'ni topish sharhda tez-tez uchraydi. - Intervyu. "
promisifyni o'zingiz yozing" —Promise.allni yozishdan keyin eng ko'p so'raladigan amaliy savol.
Xulosa
Promise.resolve(x)— tayyor qiymatdan (yoki thenable'dan) Promise; Promise bersangiz — o'shaning o'zi.Promise.reject(xato)— tayyor rad etilgan Promise.kut(ms)— Promise +setTimeout; Node'danode:timers/promises.- Promisify: callback'ning
xatoyo'li →reject,natijayo'li →resolve. Node'dautil.promisify; metod uchunbind; faqat bir martalik natijalar uchun. Promise.withResolvers()—{ promise, resolve, reject }: Promise'ni bir joyda yaratib, boshqa joyda hal qilish.Promise.try(fn)—fnni darhol chaqiradi; sinxron xato ham rad etilgan Promise bo'ladi. Node 24 da bor, Node 22 da yo'q.new Promiseni faqat callback'li API uchun ishlating — tayyor Promise'ni qayta o'ramang.
Keyingi dars: Microtask va macrotask chuqur — then va await aynan qaysi qadamda microtask yaratadi, murakkab tartib masalalari va microtask'lar taymerlarni qanday "och qoldiradi".
Manbalar
- ECMAScript spetsifikatsiyasi: "Promise.resolve", "Promise.reject", "Promise.withResolvers", "Promise.try" — tc39.es/ecma262
- TC39 takliflari: "Promise.withResolvers", "Promise.try" — github.com/tc39
- Node.js hujjatlari: "util.promisify", "Timers Promises API", "fs/promises" — nodejs.org/api
- MDN: "Promise.withResolvers()", "Promise.try()" — developer.mozilla.org
- web-features (Baseline):
promise-withresolvers,promise-try— github.com/web-platform-dx/web-features
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!