آشنایی با Promise.all در جاوااسکریپت
پرامیس یک مکان برای نگهداری مقداری میباشد که پس از مدتی در دسترس خواهد بود؛ میباشد یعنی عملیات گرفتن مقدار مدتی زمان بر هست، مانند گرفتن دیتا از دیتابیس یا ارسال درخواست به سرویس های خارجی جهت گرفتن دیتا.
پرامیس به ما کمک میکند که عملیات های ناهمزمان را بهتر مدیریت کنیم.
جاوااسکریپت یک تابع کمکی به اسم Promise.all() را در اختیار برنامه نویس قرار میدهد، ورودی آن یک آرایه ای از پرامیس ها میباشد و این متد تمامی پرامیس های موجود در ورودی را همزمان اجرا میکند و خروجی آن ها را نیز در قالب یک آرایه برمیگرداند و در اختیار ما قرار میدهد.
خب بریم بررسی کنیم که Promise.all چطور کار میکند:
1- Promise.all()
همانطور که بالاتر اشاره کردم این helper یا کمک کننده یک ورودی از پرامیس ها را دریافت میکند و خروجی آن نیز آرایه ای به صورت پرامیس هست که ترتیب آیتم های آرایه دقیقا به ترتیب ورودی میباشد و میتوانیم با کمک then و catch خروجی آن را مدیریت کنیم.
const allPromise = Promise.all([promise1, promise2]);
allPromise.then(values => {
console.log(values); // [resolvedValue1, resolvedValue2]
}).catch(error => {
console.log(error); // rejectReason of any first rejected promise
});
اما بخوام یک نکته بگم آن است که ما فقط به then و catch محدود نیستیم و میتوانیم از async و await نیز استفاده کنیم :
const allPromise = Promise.all([promise1, promise2]);
try {
const values = await allPromise;
console.log(values); // [resolvedValue1, resolvedValue2]
} catch (error) {
console.log(error); // rejectReason of any first rejected promise
}
خب قسمت جالب promise همانطور که گفتم ترتیب ورودی ها خیلی مهمه که حواستون بهش باشه چون خروجی هم دقیقا بر همان اسا میباشد و اینجا یک دیاگرام براتون حاضر کردم که نحوه ی تایید یا رد شدن درخواست ها یا عملیات های Promise را نشان میدهد:
All promises are fullfilled
اما اگر حتی یکی از پرامیس ها رد شود تمامی عملیات ها لغو یا رد میشود:
One promise rejects
با کمک متد setTimeout دو متد جهت شبیه سازی عملیات های پرامیس پیاده سازی میکنیم یکی برای عملیات موفق یکی هم برای عملیات ناموفق یا رد شده:
function resolveTimeout(value, delay) {
return new Promise(
(resolve, reject) => setTimeout(() => resolve(value), delay)
);
}
function rejectTimeout(reason, delay) {
return new Promise(
(resolve, reject) => setTimeout(() => reject(reason), delay)
);
}
در متد resolveTimeout ما مقدار value را پس از گذشت مدت زمان delay (میلی ثانیه) با کمک resolve بر میگردانیم.
متد rejectTimeout دقیقا مانند متد resolveTimeout میباشد با این تفاوت پس گذشت زمان تعیین شده با کمک متد reject یک خطا را ایجاد میکند که نحوه ی شکست خوردن یا رد شدن عملیات پرامیسی را شبیه سازی کنیم.
به مثال زیر توجه کنید:
const allPromise = Promise.all([
resolveTimeout(['NodeJS', 'javascript'], 1000),
resolveTimeout(['NestJS', 'ExpressJS'], 1000)
]);
// wait...
const lists = await allPromise;
// after 1 second
console.log(lists);
// [['NodeJS', 'javascript'], ['NestJS', 'ExpressJS']]
در این مثال ما دو بار از متد resolveTimeout استفاده کردیم که پس از هر بار اجرا کردن این متد یک ثانیه طول میکشد تا ریسپانس را برگرداند اما با استفاده از promise.all همه ی آنها در یک زمان واحد اجرا میکند و اگر به خروجی دقت کنید دقیقا ترتیب آن مانند ورودی میباشد و حتی ما میتوانیم خروجی ها را دستراکچر کنیم :
const [resolvedOfPromise1, resolvedOfPromise2] = Promise.all([promise1, promise2])
مثال ( وجود حداقل یک خطا):
حال میخوایم یک لیستی دیگر از پرامیس ها را اجرا کنیم که حداقل یکی از آنها ریجکت شود :
const allPromise = Promise.all([
resolveTimeout(['NodeJS', 'NestJS'], 1000),
rejectTimeout(new Error('there is an error!'), 1000)
]);
try {
// wait...
const lists = await allPromise;
} catch (error) {
// after 1 second
console.log(error.message); // 'there is an error!'
}
همانطور که مشاهده کردید بعد از یک ثانیه اجرای پرامیس ریجکت شد و دیگر هیچ خروجی را برای ما برنگرداند، خب این بدین معناست که در Promise.all حتی اگر یکی از پرامیس ها در لیست اجرا نشود یا ریجکت شود کل لیست ما ریجکت خواهد شد که به این رفتار Fail-fast گفته میشود.
Promise.all([...]) یک تابع کمکی مفید است که به شما امکان می دهد عملیات ناهمزمان را به صورت موازی با استفاده از یک استراتژی Fail-fast اجرا کنید و نتایج را در یک آرایه جمع آوری کنید.
از سال ۸۹ - ۹۰ وارد حوزه ی برنامه نویسی شدم و انواع زمینه ها و شاخه های مختلف رو کار کردم تا اینکه سال ۹۵ توی حوزه ی بک اند (نود جی اس) ماندگار شدم، تجربیات خیلی زیادی رو توی این مسیر کسب کردم. شکست ها و موفقیت هایی رو هم داشتم که همه ی این موارد رو در قالب مقاله، دوره و پادکست در اختیارتون خواهم گذاشت خلاصه که وبسایت کدنایت رو سال ۱۴۰۲ توسعه دادیم که یک پلتفرم آموزشی با گروهی از اساتید خفن هستش که قراره کلی محتوا در اختیارتون بذاریم.