Ҷанбаи мусбати ваъдаҳо дар он аст, ки онҳо кодро аз боло ба поён, на аз чап ба рост, хеле беҳтар хондан мекунанд. Бо вуҷуди ин, ваъдаҳо инчунин мушкилоти худро доранд:
Кор бо ваъдаҳои сершумор дар як давр на ҳамеша қулай аст; дар баъзе мавридҳо онҳо кодро душвор мегардонанд.
Ана як масъалае, ки маънои нуктаи охиринро нишон медихад.
Фарз мекунем, ки мо ҳалқаи for дорем, ки пайдарпаии рақамҳоро аз 0 то 10 бо фосилаҳои тасодуфӣ (0–n сония) чоп мекунад. Бо истифода аз ваъдаҳо, шумо бояд ин давраро тағир диҳед, то рақамҳо бо пайдарпай аз 0 то 10 чоп карда шаванд. Ҳамин тавр, агар барои чопи як сифр 6 сония ва барои чопи як 2 сония лозим шавад, аввал сифр бояд чоп карда шавад ва сипас ақибшумории чопи он оғоз мешавад.
Ва албатта, мо барои ҳалли ин мушкилот Async/Await ё .sort истифода намебарем. Як ҳалли мисол дар охири аст.
Одатан он аз ду калимаи калидӣ иборат аст: асинхронӣ ва интизорӣ. Калимаи аввал функсияро ба асинхронӣ табдил медиҳад. Чунин функсияҳо имкон медиҳанд, ки интизор шаванд. Дар ҳама ҳолатҳои дигар, истифодаи ин функсия хатогӣ ба вуҷуд меорад.
// With function declaration
async function myFn() {
// await ...
}
// With arrow function
const myFn = async () => {
// await ...
}
function myFn() {
// await fn(); (Syntax Error since no async)
}
Async дар ибтидои эъломияи функсия ва дар ҳолати функсияи тирча дар байни аломати "=" ва қавс ҷойгир карда мешавад.
Ин функсияҳоро метавон дар объект ҳамчун усул ҷойгир кард ё дар эъломияи синф истифода бурд.
// As an object's method
const obj = {
async getName() {
return fetch('https://www.example.com');
}
}
// In a class
class Obj {
async getResource() {
return fetch('https://www.example.com');
}
}
Агар арзиши баргардонидани ибтидоӣ бошад, функсияи асинкӣ арзишро тавассути печонидани он дар ваъда бармегардонад. Агар арзиши бозгашт объекти ваъда бошад, ҳалли он дар ваъдаи нав баргардонида мешавад.
const p = Promise.resolve('hello')
p instanceof Promise;
// true
Promise.resolve(p) === p;
// true
Аммо агар дар дохили функсияи асинхронӣ хатогӣ мавҷуд бошад, чӣ мешавад?
async function foo() {
throw Error('bar');
}
foo().catch(console.log);
Агар он коркард нашавад, foo() ваъдаро бо радд бармегардонад. Дар ин ҳолат, ба ҷои Promise.resolve, Promise.reject, ки хато дорад, баргардонида мешавад.
Функсияҳои асинхронӣ ҳамеша ваъда медиҳанд, новобаста аз он ки баргардонида мешавад.
Функсияҳои асинхронӣ дар ҳар интизорӣ таваққуф мекунанд.
Интизорӣ ба ифодаҳо таъсир мерасонад. Ҳамин тавр, агар ифода ваъда бошад, функсияи асинхронӣ то иҷро шудани ваъда боздошта мешавад. Агар ифода ваъда набошад, он тавассути Promise.resolve ба ваъда табдил дода мешавад ва сипас анҷом дода мешавад.
// utility function to cause delay
// and get random value
const delayAndGetRandom = (ms) => {
return new Promise(resolve => setTimeout(
() => {
const val = Math.trunc(Math.random() * 100);
resolve(val);
}, ms
));
};
async function fn() {
const a = await 9;
const b = await delayAndGetRandom(1000);
const c = await 5;
await delayAndGetRandom(1000);
return a + b * c;
}
// Execute fn
fn().then(console.log);
Ва дар ин ҷо тавсифи он аст, ки функсияи fn чӣ гуна кор мекунад.
Пас аз даъват кардани он, сатри аввал аз const a = wait 9 табдил дода мешавад; дар const a = интизори Promise.resolve(9);.
Пас аз истифодаи Await, иҷрои функсия то ба даст овардани арзиши худ боздошта мешавад (дар ҳолати кунунӣ он 9 аст).
delayAndGetRandom(1000) иҷрои функсияи fn-ро то он даме, ки худ ба охир расад (пас аз 1 сония) таваққуф мекунад. Ин функсияи fn-ро барои 1 сония ба таври муассир қатъ мекунад.
delayAndGetRandom (1000) тавассути ҳалли арзиши тасодуфиро бармегардонад, ки он гоҳ ба тағирёбандаи b таъин карда мешавад.
Хуб, парванда бо тағирёбандаи c ба парвандаи тағирёбандаи a шабеҳ аст. Пас аз ин, ҳама чиз барои як сония қатъ мешавад, аммо ҳоло delayAndGetRandom(1000) чизе барнамегардонад, зеро он талаб карда намешавад.
Дар натиҷа, арзишҳо бо формулаи a + b * c ҳисоб карда мешаванд. Натиҷа бо истифода аз Promise.resolve бо ваъда печонида мешавад ва аз ҷониби функсия баргардонида мешавад.
Ин таваққуфҳо метавонанд генераторҳои ES6-ро ба хотир оранд, аммо дар он чизе ҳаст сабабҳои шумо.
Халли масъала
Хуб, акнун биёед ба ҳалли масъалаи дар боло зикршуда назар андозем.
async function canRejectOrReturn() {
// wait one second
await new Promise(res => setTimeout(res, 1000));
// Reject with ~50% probability
if (Math.random() > 0.5) {
throw new Error('Sorry, number too big.')
}
return 'perfect number';
}
Тавре ки шумо мебинед, дар код ягон интизорӣ ё бозгашт вуҷуд надорад. Аз ин рӯ, foo ҳамеша бо номуайян бидуни таъхири 1 сония мебарояд. Аммо ваъда ичро мешавад. Агар он хато ё рад кунад, он гоҳ UnhandledPromiseRejectionWarning даъват карда мешавад.