Promise
Promise ("va'da") โ asinxron harakat natijasini chiroyli boshqarish uchun maxsus obyekt. U callback jahannamining oldini oladi va kodni tekis, o'qilishi oson qiladi. Ushbu darsda Promise nima ekani, uning holatlari va asosiy metodlari bilan tanishamiz.
Analogiya: qo'shiqchi va muxlislar
Promise'ni tushunish uchun oddiy analogiya. Faraz qiling, mashhur qo'shiqchi bor. Muxlislar undan yangi qo'shig'i qachon chiqishini so'rab turishadi. Qo'shiqchi ularga va'da beradi: "Qo'shiq chiqqach, hammangizga xabar beraman". Muxlislar esa ro'yxatga yozilib qo'yishadi.
Bu yerda ikki ishtirokchi bor:
- Ijodkor kod (qo'shiqchi) โ biror vaqt oladigan ishni bajaradi. Bu โ "producing code";
- Iste'mol kod (muxlislar) โ natijani kutadi va u tayyor bo'lganda foydalanadi. Bu โ "consuming code".
Promise โ ularni bog'lovchi maxsus obyekt (ro'yxat kabi). U ijodkor kod tayyor bo'lganda barcha yozilgan iste'molchilarga natijani yetkazadi.
new Promise(executor) sintaksisi
Promise obyekti new Promise konstruktori bilan yaratiladi. Unga executor (bajaruvchi) deb ataluvchi funksiya uzatiladi:
const promise = new Promise(function (resolve, reject) {
// Bu yerda ijodkor (asinxron) kod turadi
// ... ish tugaganda:
// resolve(natija) -> muvaffaqiyat
// reject(xato) -> xatolik
});
Executor funksiya new Promise yaratilishi bilan darhol va avtomatik ishga tushadi. Unga JavaScript'ning o'zi ikkita funksiya-argument beradi:
resolve(value)โ ish muvaffaqiyatli tugaganda chaqiriladi, natijavalue;reject(error)โ xatolik yuz berganda chaqiriladi, xato obyektierror.
resolve va reject funksiyalarini biz o'zimiz yozmaymiz โ ularni JavaScript tayyor holda executor'ga beradi. Bizning vazifamiz โ ish natijasiga qarab shulardan birini chaqirish.Promise holatlari
Har bir Promise obyekti ichida ikkita muhim ichki xususiyat bor: state (holat) va result (natija). Promise uch holatdan birida bo'ladi:
- pending (kutilmoqda) โ boshlang'ich holat. Ish hali tugamagan, natija yo'q;
- fulfilled (bajarilgan) โ
resolve(value)chaqirildi. Ish muvaffaqiyatli tugadi; - rejected (rad etilgan) โ
reject(error)chaqirildi. Xatolik yuz berdi.
Muhim jihat: Promise dastlab pending holatda bo'ladi, so'ng bir marta โ yo fulfilled, yo rejected holatiga o'tadi. Bu o'tish qaytmas: bir marta hal bo'lgan Promise'ni o'zgartirib bo'lmaydi.
// Muvaffaqiyatli Promise:
const yaxshi = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("Bajarildi!"); // 1 sekunddan keyin fulfilled
}, 1000);
});
// Rad etilgan Promise:
const yomon = new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("Nimadir noto'g'ri ketdi")); // 1 sekunddan keyin rejected
}, 1000);
});
resolve yoki rejectdan faqat bittasi hisobga olinadi โ birinchi chaqiruv. Keyingi barcha chaqiruvlar e'tiborsiz qoldiriladi. Shuningdek, resolve va reject faqat bitta argument qabul qiladi, qolganlari inobatga olinmaydi..then โ natijani qabul qilish
Promise'ni yaratdik, endi uning natijasini qabul qilish kerak (iste'mol kod). Buning eng asosiy metodi โ .then. U ikkita callback qabul qiladi:
promise.then(
function (result) {
// Promise fulfilled bo'lsa: bu funksiya natija bilan chaqiriladi
console.log(result);
},
function (error) {
// Promise rejected bo'lsa: bu funksiya xato bilan chaqiriladi
console.log(error);
}
);
Ya'ni: birinchi funksiya โ muvaffaqiyat uchun, ikkinchisi โ xatolik uchun. Amaliy misol:
const promise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("Salom, dunyo!");
}, 1000);
});
promise.then(
function (result) {
console.log("Natija: " + result); // 1 sekunddan keyin: Natija: Salom, dunyo!
},
function (error) {
console.log("Xato: " + error);
}
);
Agar bizni faqat muvaffaqiyat qiziqtirsa, .thenga faqat bitta funksiya uzatishimiz mumkin:
promise.then(function (result) {
console.log(result); // faqat muvaffaqiyatni boshqaradi
});
.catch โ faqat xatolikni boshqarish
Agar bizni faqat xatolik qiziqtirsa, .then(null, funksiya) yozish mumkin. Ammo buning uchun qulayroq va o'qilishi oson metod bor โ .catch:
const promise = new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("Voy, xatolik!"));
}, 1000);
});
// .catch(f) โ bu .then(null, f) bilan bir xil
promise.catch(function (error) {
console.log("Ushlangan xato: " + error.message); // Ushlangan xato: Voy, xatolik!
});
.catch(f) โ bu .then(null, f)ning qisqacha yozuvi. Faqat xatolikni boshqarish uchun ishlatiladi va kodni ancha o'qilishi oson qiladi..finally โ yakuniy tozalash
.finally โ Promise qanday tugashidan qat'i nazar (muvaffaqiyat yoki xatolik) doim chaqiriladigan metod. U ko'pincha tozalash ishlari uchun ishlatiladi: masalan, yuklanish indikatorini (spinner) o'chirish.
new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("Ma'lumot");
}, 1000);
})
.finally(function () {
// Doim ishlaydi: indikatorni o'chirish va h.k.
console.log("Ish tugadi (muvaffaqiyat yoki xato โ farqi yo'q)");
})
.then(function (result) {
console.log("Natija: " + result);
});
.finallyning muhim xususiyatlari:
- U argumentsiz funksiya qabul qiladi โ natija yoki xatoni bilmaydi, chunki uning vazifasi โ umumiy tugatish ishlari;
- U natijani o'zgartirmaydi โ natija yoki xato keyingi
.then/.catchga o'zgarishsiz o'tadi; - Har ikki holatda ham (fulfilled/rejected) ishlaydi.
.finallyni sinf-metodlaridagi try...finally bilan solishtiring: ikkalasi ham "nima bo'lishidan qat'i nazar bu kodni bajar" degan g'oyani ifodalaydi.Promise'ning callback'dan afzalligi
Callback bilan solishtirganda Promise nima yutuq beradi?
- Tabiiy tartib โ avval asinxron ishni yozamiz, keyin natija bilan nima qilishni. Callback'da esa avval "keyin nima qilish"ni yozib, keyin ishni chaqirardik;
- Ko'p iste'molchi โ bitta Promise'ga
.thenni bir necha marta ulash mumkin; - Zanjirlash โ
.thenlarni ketma-ket ulab, tekis kod yozish mumkin (keyingi darsda); - Xatoliklarni yagona joyda boshqarish โ
.catchorqali.
Xulosa
- Promise โ asinxron natijani boshqaruvchi obyekt,
new Promise(executor)bilan yaratiladi; - Executor darhol ishga tushadi va
resolve(value)yokireject(error)chaqiradi; - Holatlar: pending → fulfilled yoki rejected (qaytmas o'tish);
.then(f1, f2)โ natija va xatoni qabul qiladi;.catch(f)โ faqat xatoni boshqaradi (=.then(null, f));.finally(f)โ natijadan qat'i nazar doim ishlaydigan tozalash.