Promise API
Promise klassida bir nechta foydali statik metod bor. Ular bir nechta promise'ni birga boshqarishga yordam beradi. Ushbu darsda ularning har birini misol bilan ko'rib chiqamiz.
Promise.all
Ko'pincha bir nechta promise'ni parallel ishga tushirib, hammasi tugashini kutish kerak bo'ladi. Masalan, bir nechta URL'dan ma'lumot yuklab, hammasi kelgach ishlov berish. Aynan shu uchun Promise.all mavjud.
Promise.all promise'lar (yoki iteratsiyalanadigan obyekt, odatda massiv) qabul qiladi va yangi promise qaytaradi. Bu yangi promise barcha berilgan promise'lar bajarilganda (fulfilled) natijalar massivi bilan tugaydi.
Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then(alertResult => console.log(alertResult)); // [1, 2, 3]
Ko'p qo'llaniladigan hiyla โ massivdagi ma'lumotlarni promise'lar massiviga aylantirib, keyin ularni Promise.all'ga o'rash:
let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/remy',
'https://api.github.com/users/jeresig'
];
// har bir url uchun fetch promise'ini yaratamiz
let requests = urls.map(url => fetch(url));
// Promise.all barcha so'rovlar tugashini kutadi
Promise.all(requests)
.then(responses => {
for (let response of responses) {
console.log(response.status); // har bir javob statusi
}
});
Promise.all darhol o'sha xato bilan reject bo'ladi. Qolgan promise'lar natijasi mutlaqo e'tiborga olinmaydi โ ular bekor qilinmaydi, lekin natijasi tashlab yuboriladi.Promise.all([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Xatolik!')), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).catch(console.log); // Error: Xatolik!
Yuqoridagi misolda ikkinchi promise 2 soniyadan keyin reject bo'ladi. Shu zahoti Promise.all ham reject bo'ladi va catch ishga tushadi. Uchinchi promise (3 soniya) hali tugamagan bo'lsa ham, uning natijasi hech qayerda ko'rinmaydi.
Promise.allSettled
Promise.all birinchi xatoda to'xtaydi. Ba'zan esa bizga har bir promise natijasi kerak โ qaysi biri muvaffaqiyatli, qaysi biri xato bo'lganidan qat'i nazar. Aynan shunda Promise.allSettled ishlatiladi.
Promise.allSettled barcha promise'lar settled (yakunlangan โ fulfilled yoki rejected) bo'lishini kutadi va hech qachon reject bo'lmaydi. U natijalar massivini qaytaradi, unda har bir element quyidagicha:
{status: "fulfilled", value: natija}โ muvaffaqiyatli tugagan bo'lsa;{status: "rejected", reason: xato}โ xatoga uchragan bo'lsa.
let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/remy',
'https://no-such-url'
];
Promise.allSettled(urls.map(url => fetch(url)))
.then(results => {
results.forEach((result, num) => {
if (result.status == 'fulfilled') {
console.log('Javob ' + urls[num] + ': ' + result.value.status);
}
if (result.status == 'rejected') {
console.log('Xato ' + urls[num] + ': ' + result.reason);
}
});
});
Yuqorida results quyidagicha bo'ladi (soddalashtirilgan):
[
{status: 'fulfilled', value: ...birinchi javob...},
{status: 'fulfilled', value: ...ikkinchi javob...},
{status: 'rejected', reason: ...xato obyekti...}
]
Promise.race
Promise.race Promise.allga o'xshaydi, lekin faqat birinchi yakunlangan promise'ni kutadi. "Race" โ poyga degani: qaysi promise birinchi tugasa (fulfilled yoki rejected โ farqi yo'q), uning natijasi/xatosi butun natija bo'ladi.
Promise.race([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Xatolik!')), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(console.log); // 1
Bu yerda birinchi promise eng tez (1 soniya) tugadi, shuning uchun natija 1 bo'ldi. Undan keyingi promise'lar natijasi butunlay e'tiborga olinmaydi.
Promise.race birinchi yakunlangan promise reject bo'lsa, o'zi ham reject bo'ladi. Ya'ni g'olib promise xato bilan tugasa, natija ham xato bo'ladi.Promise.any
Promise.any Promise.racega o'xshaydi, lekin faqat birinchi muvaffaqiyatli (fulfilled) promise'ni kutadi. Ya'ni u xatolarni "tashlab", birinchi muvaffaqiyatli natijani qaytaradi.
Promise.any([
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Xatolik!')), 1000)),
new Promise((resolve, reject) => setTimeout(() => resolve(1), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(console.log); // 1
Bu yerda birinchi promise (1 soniya) reject bo'ldi, lekin Promise.any uni e'tiborga olmaydi. Ikkinchi promise (2 soniya) โ birinchi muvaffaqiyatli natija bo'lgani uchun natija 1 bo'ldi.
Agar barcha promise'lar reject bo'lsa, Promise.any maxsus AggregateError xatosi bilan reject bo'ladi. Uning errors maydonida barcha xatolar saqlanadi:
Promise.any([
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Xato 1')), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Xato 2')), 2000))
]).catch(error => {
console.log(error.constructor.name); // AggregateError
console.log(error.errors[0]); // Error: Xato 1
console.log(error.errors[1]); // Error: Xato 2
});
Promise.resolve va Promise.reject
Zamonaviy kodda bu ikki metod kamdan-kam kerak bo'ladi, chunki async/await ularning o'rnini bosadi. Ammo ularni bilib qo'yish foydali.
Promise.resolve(value) โ natijasi value bo'lgan bajarilgan (resolved) promise yaratadi:
let promise = Promise.resolve(value);
// bu quyidagi bilan bir xil:
let promise2 = new Promise(resolve => resolve(value));
U funksiya promise qaytarishi kerak bo'lganda, lekin qiymat allaqachon tayyor bo'lganda ishlatiladi. Masalan, keshdan qiymat qaytarishda:
let cache = new Map();
function loadCached(url) {
if (cache.has(url)) {
// keshdagi qiymatni promise sifatida qaytaramiz
return Promise.resolve(cache.get(url));
}
return fetch(url)
.then(response => response.text())
.then(text => {
cache.set(url, text);
return text;
});
}
Promise.reject(error) โ natijasi error bo'lgan reject qilingan promise yaratadi. U amalda deyarli ishlatilmaydi.
Xulosa
Promise klassining 6 ta statik metodi:
Promise.all(promises)โ hammasini kutadi, natijalar massivini beradi. Bittasi xato bo'lsa โ hammasi xato;Promise.allSettled(promises)โ hammasini kutadi, har biri uchunstatusva natija/xato beradi;Promise.race(promises)โ birinchi yakunlangan (fulfilled yoki rejected) natijani beradi;Promise.any(promises)โ birinchi muvaffaqiyatli natijani beradi; hammasi xato bo'lsa โAggregateError;Promise.resolve(value)โ tayyor bajarilgan promise yaratadi;Promise.reject(error)โ tayyor reject qilingan promise yaratadi.