Promise, async/await

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:

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 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:

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:

.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?

Xulosa