Промисҳо
Ин барои чӣ лозим аст
Дар мавзӯи гузашта натиҷаи асинхрониро тавассути callback медоданд ва ҳангоми якчанд қадам «зинапоя»-и
функсияҳои ба ҳам ҷойгир пайдо мешуд. Промис (Promise — «ваъда») — объектест, ки натиҷаи ояндаро
ифода мекунад. Онро бо return-и оддӣ аз функсия баргардондан, дар тағйирёбанда нигоҳ доштан, ба пеш
додан ва ба натиҷа обуна шудан мумкин аст.
Тамоми JavaScript-и муосир бар промисҳо сохта шудааст: fetch (дархостҳо ба сервер), хондани файлҳо дар
Node.js, async/await, бор кардани додаҳо дар React. Ҳатто агар await нависед, дар зери он ҳамеша
промисҳо ҳастанд — барои ҳамин онҳоро фаҳмидан лозим аст.
Се ҳолат
Промис ҳамеша дар яке аз се ҳолат аст:
| Ҳолат | Маънояш |
|---|---|
pending (интизорӣ) |
натиҷа ҳоло нест |
fulfilled (иҷрошуда) |
натиҷа ҳаст — қимат |
rejected (радшуда) |
хато рух дод — сабаб ҳаст |
Аз интизорӣ промис ба яке аз ду ҳолати ниҳоӣ як бор мегузарад ва дигар тағйир намеёбад.
Сохтани промис: new Promise
function delay(ms) {
return new Promise((resolve) => {
setTimeout(() => resolve("тайёр"), ms);
});
}
console.log("Интизорем...");
delay(100).then((result) => console.log(result));
Натиҷа:
Интизорем...
тайёр
- Ба
new Promise(…)функсияи «иҷрокунанда»-ро медиҳанд. Вай фавран оғоз мешавад ва ду функсия мегирад:resolve(қимат)— «бомуваффақият иҷро шуд» ваreject(хато)— «нашуд». .then(callback)— «вақте натиҷа шуд, callback-ро бо он даъват кун».
Мисол бо хато:
function checkAge(age) {
return new Promise((resolve, reject) => {
if (age >= 18) resolve("Дастрасӣ кушода шуд");
else reject(new Error("Ҳоло барвақт аст"));
});
}
checkAge(20).then((text) => console.log(text));
checkAge(12)
.then((text) => console.log(text))
.catch((err) => console.log("Хато: " + err.message));
Натиҷа:
Дастрасӣ кушода шуд
Хато: Ҳоло барвақт аст
.catch(callback) радшавиро медорад. Ба reject одатан объекти Error-ро медиҳанд, мисли throw.
finally
.finally(callback) дар ҳар ҳолат иҷро мешавад — муваффақ ё не. Масалан, барои пинҳон кардани нишондиҳандаи боркунӣ:
checkAge(12)
.then((text) => console.log(text))
.catch((err) => console.log("Хато: " + err.message))
.finally(() => console.log("Боркунӣ тамом шуд"));
Занҷирҳои then
Қуввати асосии промисҳо: then худаш промиси нав бармегардонад. Он чи callback баргардонд — промиси
навбатӣ бо ҳамон иҷро мешавад. Ҳамин тавр қадамҳо бе ҷойгиршавӣ паси ҳам меоянд:
Promise.resolve(2)
.then((x) => x * 10) // 20
.then((x) => x + 1) // 21
.then((x) => console.log("Ҳосил: " + x));
Натиҷа:
Ҳосил: 21
Агар callback промис баргардонад, занҷир онро интизор мешавад:
const wait = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
wait(50, "Аня")
.then((name) => wait(50, name + " аз Душанбе")) // боз як промисро интизор мешавем
.then((text) => console.log(text));
Натиҷа:
Аня аз Душанбе
Бо «дӯзахи callback-ҳо» аз мавзӯи гузашта муқоиса кунед: қадамҳо ҳамчун рӯйхати ҳамвор навишта шудаанд.
Хатоҳо дар занҷир
Хато (тавассути reject ё throw-и оддӣ дар дохили then) ҳамаи then-ҳои навбатиро мегузарад ва ба
catch-и наздиктарин меафтад. Барои ҳамин як catch дар охир барои тамоми занҷир кифоя аст:
Promise.resolve(1)
.then((x) => {
throw new Error("дар қадами 2 шикаст");
})
.then((x) => console.log("ин қадам гузаронида мешавад"))
.catch((err) => console.log("Доштем: " + err.message))
.then(() => console.log("Баъд аз catch занҷир идома дорад"));
Натиҷа:
Доштем: дар қадами 2 шикаст
Баъд аз catch занҷир идома дорад
catch ҳам промис бармегардонад: он чи вай баргардонд, қимати нав мешавад. Ҳамин тавр қимати пешфарзро
мегузоранд: .catch(() => []).
Якчанд промис якбора
Аксар вақт якчанд вазифаро параллелӣ оғоз карда, ҳамаашонро интизор шудан лозим аст. Барои ин
усулҳои статикии Promise ҳастанд:
const wait = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
const start = Date.now();
Promise.all([wait(100, "A"), wait(100, "B"), wait(100, "C")]).then((values) => {
console.log(values);
console.log("Зудтар аз 200 мс: " + (Date.now() - start < 200));
});
Натиҷа:
["A","B","C"]
Зудтар аз 200 мс: true
Се интизорӣ ҳар кадом 100 мс тақрибан 100 мс гирифт, на 300: онҳо якбора мерафтанд.
| Усул | Кай иҷро мешавад | Натиҷа |
|---|---|---|
Promise.all(arr) |
ҳама иҷро шуданд | массиви қиматҳо бо тартиби массив; ҳангоми хатои аввал — рад мешавад |
Promise.allSettled(arr) |
ҳама ба ҳар роҳ тамом шуданд | массиви { status, value } ё { status, reason } |
Promise.race(arr) |
аввалин тамом шуд | қимат ё хатои он |
Promise.any(arr) |
аввалин муваффақ | қимати он |
allSettled вақте қулай аст, ки як нокомӣ набояд ҳамаро вайрон кунад:
Promise.allSettled([Promise.resolve(1), Promise.reject(new Error("не")), Promise.resolve(3)]).then((results) => {
console.log(results.map((r) => (r.status === "fulfilled" ? r.value : "хато")));
});
Натиҷа:
[1,"хато",3]
race бошад — усули гузоштани маҳдудияти вақт: «агар ҷавоб дар 3 сония наояд — хато».
Дар дохил чӣ гуна кор мекунад: микровазифаҳо
Callback-ҳои then, catch ва finally ҳеҷ гоҳ фавран даъват намешаванд, ҳатто агар промис аллакай иҷро
шуда бошад. Онҳо ба навбати махсус — микровазифаҳо меафтанд. Давраи рӯйдодҳо онро фавран баъд аз коди
ҷорӣ ва пеш аз вазифаҳои оддӣ, мисли таймерҳо, коркард мекунад:
console.log("1: коди синхронӣ");
setTimeout(() => console.log("4: таймер"), 0);
Promise.resolve().then(() => console.log("3: then"));
console.log("2: коди синхронӣ");
Натиҷа:
1: коди синхронӣ
2: коди синхронӣ
3: then
4: таймер
Тартиб чунин аст: тамоми коди синхронӣ → ҳамаи микровазифаҳо (промисҳо) → вазифаи навбатӣ аз навбат (таймер, клик) → боз микровазифаҳо → …
Боз як хосияти муҳим: функсияи иҷрокунанда дар new Promise синхронӣ, фавран ҳангоми сохтан иҷро
мешавад. Танҳо аксуламалҳо ба натиҷа асинхронӣ мебошанд.
Хатоҳои маъмул
return-и фаромӯшшуда дарthen..then((x) => { x * 2; })ба пешundefinedмедиҳад. Ё тирчаи кӯтоҳ(x) => x * 2, ёreturn.- Промис дар дохили
thenбеreturn. Занҷир онро интизор намешавад ва хатоҳояшро касе намедорад. catchнест. Промиси радшуда бе коркардкунанда — «хатои коркарднашуда», дар Node.js вай барномаро қатъ мекунад.- Паси ҳам интизор шудани он чи параллелӣ мумкин аст. Боркуниҳои мустақилро якҷоя оғоз кунед ва бо
Promise.allинтизор шавед. - Кӯшиши синхронӣ гирифтани қимат.
const x = delay(100);— дарxпромис аст, на натиҷа. Натиҷа танҳо дарthen(ё боawait, мавзӯи навбатӣ) дастрас аст.
Ёддошт
| Чӣ | Чӣ тавр |
|---|---|
| Сохтан | new Promise((resolve, reject) => { ... }) |
| Промиси тайёр | Promise.resolve(x), Promise.reject(err) |
| Натиҷа | .then((value) => ...) |
| Хато | .catch((err) => ...) |
| Дар ҳар ҳолат | .finally(() => ...) |
| Ҳамаро интизор шудан | Promise.all([...]) |
| Ҳама, ҳатто бо хатоҳо | Promise.allSettled([...]) |
| Кӣ аввал | Promise.race([...]) |
| Тартиб | коди синхронӣ → микровазифаҳо (then) → таймерҳо |