Promise — asoslar, then, catch, finally
Muammodan boshlaylik
Callback Hell da ko'rgan muammolarimiz:
- Har qadam oldingi qadamning ichiga kiradi — piramida hosil bo'ladi
- Xato boshqaruvi har qadamda takrorlanadi
- Parallel so'rovlarni kutish — qo'lda flag, takror kod
Promise bu uchala muammoni hal qiladi. Avval Callback Hell ko'rinishi, keyin Promise bilan:
// Callback Hell — 4 qadam, 4 daraja chuqurlik
getUser(id, function(e, user) {
getPosts(user.id, function(e, posts) {
getComments(posts[0].id, function(e, comments) {
render(user, posts, comments);
});
});
});
// Promise — 4 qadam, tekis zanjir
getUser(id)
.then(user => getPosts(user.id))
.then(posts => getComments(posts[0].id))
.then(comments => render(comments))
.catch(err => xatoBoshqar(err));
Ikkinchisida piramida yo'q. Bitta .catch() barcha qadamlarning xatosini ushlaydi.
Promise nima?
Promise — "kelajakda qiymat bo'ladi" degan va'da. Hozir yo'q, lekin tayyor bo'lganda bildiriladi.
Hayotiy o'xshatma
Restorandagi buyurtma. Siz kelib: "bir porsiya lag'mon" dedingiz. Ofitsiant sizga chek berdi. Bu chek — va'da: "taom tayyor bo'lganda sizga olib kelamiz". Siz o'tirasiz, do'stingiz bilan gaplashasiz. Taom tayyor bo'lganda ofitsiant keltiradi. Agar mahsulot tugagan bo'lsa — kelib aytadi.
Chek — hozir taom emas. Lekin taom kelishiga ishonch. Kutish vaqtida siz boshqa narsalar qilasiz.
JavaScript da Promise — o'sha chek. Hozir qiymat yo'q, lekin kelajakda bo'ladi.
Promise ning uch holati
Promise yaratilganida — pending (kutilmoqda). Keyin ikki yo'nalishdan biri:
pending (kutilmoqda)
│
├──→ fulfilled (muvaffaqiyatli) — .then() ishlaydi
│
└──→ rejected (muvaffaqiyatsiz) — .catch() ishlaydi
Bir marta fulfilled yoki rejected bo'lgan Promise o'zgarmaydi. Restorandagi o'xshatma bilan: taom bir marta keldi — bo'ldi. Yoki "tugagan" deb aytildi — bo'ldi. Ikkinchi marta o'zgarmaydi.
Promise yaratish
const va_da = new Promise(function(resolve, reject) {
// Bu yerda asinxron ish bajariladi
const muvaffaqiyat = true;
if (muvaffaqiyat) {
resolve("Natija tayyor!"); // ← fulfilled
} else {
reject(new Error("Xato!")); // ← rejected
}
});
resolve — "va'da bajari ldi, mana natija". reject — "va'da bajarilmadi, mana sabab".
.then() — natija kelganda
.then() — Promise fulfilled bo'lganda ishlaydigan funksiya.
const va_da = new Promise(function(resolve) {
setTimeout(function() {
resolve({ ism: "Jasur", yosh: 25 });
}, 1000); // 1 soniyadan keyin natija keladi
});
va_da.then(function(foydalanuvchi) {
console.log(foydalanuvchi.ism); // "Jasur" — 1 soniyadan keyin
});
Zanjir — .then() dan .then() ga
.then() har doim yangi Promise qaytaradi. Bu tufayli zanjir hosil bo'ladi — bir .then() natijasi keyingi .then() ga o'tadi.
getUser(id)
.then(function(user) {
return getPosts(user.id); // ← yangi Promise qaytarildi
})
.then(function(posts) {
// getPosts tugagandan keyingina shu yerga keladi
return posts.filter(p => p.faol);
})
.then(function(faolPostlar) {
console.log(faolPostlar);
});
Nima uchun zanjir ishlaydi? .then() ichidan qaytarilgan narsa — keyingi .then() ning argumenti bo'ladi. Agar Promise qaytarilsa — u tugaguncha kutiladi.
.catch() — xato kelganda
.catch() — zanjirdagi istalgan joydan xato chiqsa, uni ushlaydi. Bitta .catch() barcha qadamlar uchun.
getUser(id)
.then(user => getPosts(user.id))
.then(posts => getComments(posts[0].id))
.then(render)
.catch(function(xato) {
// Yuqoridagi istalgan qadamdan xato chiqsa — shu yerga tushadi
console.error("Nimadir xato ketdi:", xato.message);
});
Callback Hell da har qadamda if (xato) return; yozish kerak edi. Promise da — bir marta.
.finally() — xato bo'lsa ham, bo'lmasa ham
.finally() — natija qanday bo'lishidan qat'i nazar ishlaydigan funksiya. Tozalash ishlari uchun.
Hayotiy o'xshatma
Shifoxonaga operatsiya uchun kirdingiz. Operatsiya muvaffaqiyatli bo'lsa ham, bo'lmasa ham — operatsiya xonasini dezinfektsiya qilishadi. Bu ish har doim bajariladi, natijaga qarab emas.
let yuklanmoqda = true;
fetch("/api/users")
.then(res => res.json())
.then(data => ko_rsat(data))
.catch(err => xatoBoshqar(err))
.finally(function() {
yuklanmoqda = false; // ← har holda yuklanish belgisi o'chiriladi
spinner.hide();
});
Promise.resolve va Promise.reject
Ba'zan darhol fulfilled yoki rejected Promise kerak:
Promise.resolve(42).then(n => console.log(n)); // 42 — darhol
Promise.reject(new Error("xato"))
.catch(err => console.error(err.message)); // "xato" — darhol
Bu qachon kerak? Funksiya ba'zan keshlangan natijani sinxron qaytarsa, ba'zan serverdan asinxron olsa — ikkalasini bir xil ko'rinishga keltirish uchun:
function malumatOl(id) {
const kesh = keshdan(id);
if (kesh) {
return Promise.resolve(kesh); // ← darhol, keshdan
}
return serverdan(id); // ← sekin, serverdan
}
// Ikkala holda ham .then() bilan ishlash mumkin
malumatOl(5).then(data => console.log(data));
Tez-tez uchraydigan xatolar
.then() da return unutish:
Bu eng ko'p chiqadigan xato. .then() ichida return yo'q bo'lsa — keyingi .then() undefined oladi.
getUser(id)
.then(function(user) {
getPosts(user.id); // ❌ return yo'q
})
.then(function(posts) {
console.log(posts); // undefined — getPosts natijasi qaytarilmadi
});
// ✅ return bilan
getUser(id)
.then(function(user) {
return getPosts(user.id); // ✅
})
.then(function(posts) {
console.log(posts); // to'g'ri
});
.catch() qo'ymaslik:
.catch() bo'lmasa — xato jimgina yo'qoladi. Konsol da "UnhandledPromiseRejection" ogohlantirmasi chiqadi, lekin kod ishlab ketaveradi — noto'g'ri holda.
fetch("/api")
.then(res => res.json())
.then(data => ko_rsat(data));
// ❌ .catch() yo'q — xato bo'lsa bilinmaydi
// ✅
fetch("/api")
.then(res => res.json())
.then(data => ko_rsat(data))
.catch(err => xatoBoshqar(err));
Xulosa
Promise — kelajakdagi qiymat uchun va'da. Uch holat: pending → fulfilled yoki rejected.
.then(fn) — muvaffaqiyatli natijada. Zanjir hosil qiladi.
.catch(fn) — xatoda. Zanjirdagi istalgan qadamning xatosini ushlaydi.
.finally(fn) — har holda. Tozalash ishlari uchun.
Callback Hell o'rniga — tekis zanjir. Bitta .catch() barcha xatolar uchun. Parallel so'rovlar uchun Promise.all — keyingi darslarda.
Keyingi dars
38-dars: Promise kombinatorlari — all, allSettled, race, any