سلام دوستان. Promise که برای مدیریت کردن عملیات ناهمگام استفاده میشه، یکی از کاربردیترین ویژگیهای جاوااسکریپت هست که از ES6 به این زبان اضافه شده. توی این قسمت میخوایم این موضوع کاربردی رو بررسی کنیم.
عملیات ناهمگام به عملیاتی گفته میشه جدا از روند اصلی برنامه پردازش میشه
توی جاوااسکریپت، تابع setTimeout یکی از معروفترین مثالها برای درک مفهوم عملیات ناهمگام هست. با این تابع میتونیم قطعه کدی رو بعد از یک تأخیر معین اجرا کنیم. کد زیر رو در نظر بگیرین:
ورودی اول setTimeout یک تابع هست و شامل عملیاتی میشه که میخوایم اون رو با تأخیر انجام بدیم. ورودی دوم مدت زمان تأخیر به میلیثانیه هست. اینجا 2000 یعنی 2 ثانیه.
با زدن دکمه ► میبینیم که ابتدا alert خط ۵ نمایش داده میشه و بعد از ۲ ثانیه alert خط ۲. این یعنی یک عملیات ناهمگام داریم. شاید انتظار داشتیم که جاوااسکریپت خط به خط کدهای ما رو بررسی کنه و خروجیها رو نمایش بده. اما وقتی که جاوااسکریپت به قسمتی از کد رسید که شامل یک عملیات ناهمگام بود، منتظر نتیجه این قسمت نموند و به ادامه بررسی خطهای بعدی پرداخت.
توی جاوااسکریپت، یک سری عملیات مثل اتصال به یک منبع خارجی با Ajax و WebSocket و یا خوندن و نوشتن اطلاعات توی دیتابیس و هارددیسک، جدا از روند اصلی برنامه اجرا میشن. این یعنی عملیات ناهمگام.
چطوری میتونیم بعد از به پایان رسیدن یک عملیات ناهمگام کاری رو انجام بدیم؟ مثلاً توی کد بالا ابتدا صبر کنیم کار تابعی که به پاس دادیم تموم بشه و بعد با مقدار 2 رو بگیریم؟ باید راهی باشه که بتونیم عملیات ناهمگام رو مدیریت کنیم. با این کار رو میتونیم انجام بدیم 👌
پرامیسها برای مدیریت کردن عملیات ناهمگام استفاده میشن. نحوه نوشتن یک پرامیس خیلی راحته. ابتدا با ساختار اون آشنا بشیم و بعد مثال بالا رو با پرامیس خواهیم نوشت:
new Promise(function (resolve, reject) {
// do something ...
})
همونطور که میبینیم، یک پرامیس با ساختن یک نمونه از کلاس Promise با استفاده از کلمهکلیدی new ساخته میشه. کلاس پرامیس فقط یک آرگومان میگیره و اون هم یک تابع هست. این تابع که توی اون باید عملیات ناهمگامِمون رو بنویسیم، بلافاصله وقتی یک پرامیس ساخته شد اجرا میشه.
حالا بیاین مشکلی که توی مثالمون داشتیم رو با پرامیسها حل کنیم تا با ساختار اون بیشتر آشنا بشیم. کد زیر رو با دکمه ► اجرا کنین:
همونطور که میبینیم تابعی که به پرامیس پاس دادیم دو تا پارامتر میگیره که اولی resolve و دومی reject هست:
new Promise(function (<<resolve>>, <<reject>>) {
// ...
هر دو پارامتر باید به شکل یک تابع توی پرامیس صدا زده بشن. یعنی:
new Promise(function (resolve, reject) {
>> resolve();
// or
>> reject();
});
ما توی پرامیس باید به جاوااسکریپت بگیم که کارِ ما به پایان رسید. چون جاوااسکریپت خودش متوجه به پایان رسیدن این عملیات نمیشه. وقتی عملیات ما به پایان رسید، اگر خروجی کار موفقیتآمیز بود، باید resolve رو صدا بزنیم و اگر خطا داشت reject.
چرا باید به جاوااسکریپت بگیم که عملیات ما به پایان رسید؟ برای اینکه بتونیم بعد از به پایان رسیدن عملیات ناهمگام، کار مد نظرمون رو انجام بدیم. توی مثالی که داشتیم، کار مد نظرمون رو به این صورت انجام دادیم:
welcome.<<then>>(function () {
alert(2);
});
همونطور که میبینیم از متغیر welcome که مقدار اون یک پرامیس هست، یک متد به اسم then رو صدا زدیم و به اون تابعی رو پاس دادیم. این تابع بلافاصله زمانی اجرا میشه که ما توی پرامیس resolve رو صدا زده باشیم! پس کاری که میخوایم بعد از به پایان رسیدن عملیات ناهمگام اجرا بشه رو با then انجام میدیم.
اگه عملیات ناهمگام با خطا مواجه شد، باید توی پرامیس reject رو صدا بزنیم:
const welcome = new Promise(function (resolve, reject) {
const status = 'failed';
setTimeout(() => {
if (status === 'failed') {
>> reject();
}
}, 2000);
});
این کار به جاوااسکریپت میگه که عملیات ناهمگاممون موفقیتآمیز نبود. اگه بخوایم توی برنامه، reject شدن یک پرامیس رو مدیریت کنیم از متد catch که مشابه then هست استفاده میکنیم:
همونطور که میبینیم کدی که توی خط ۱۵ نوشتیم تحت هر شرایطی اجرا میشه. تابعی که به finally پاس دادیم هیچ آرگومانی قبول نمیکنه. چون نتیجه عملیات براش مهم نیست.
بدون استفاده از finally کد بالا رو باید اینطوری مینوشتیم:
توی این تابع یک پرامیس نوشتیم که توی اون اسکریپت رو به صفحه اضافه میکنیم و به محض اینکه اسکریپت دانلود بشه، پرامیس resolve میشه. توی تابع loadScript یک پرامیس داره return میشه. پس خروجی این تابع یک پرامیس هست.
حالا میخوایم کتابخونه Axios که محبوبترین ابزار برای ارسال درخواستهای Ajax هست رو به صفحه اضافه و از اون استفاده کنیم:
الان مقدار متغیر loadAxios یک پرامیس هست و به محض اینکه اسکریپت مد نظرمون لود بشه میخوایم از اون استفاده کنیم. از متدهای then یا catch به صورت زیر استفاده میکنیم:
loadAxios.then(() => {
// Axios is loaded
axios.get(path);
});
همونطور که میدونیم کتابخونه Axios هم مبتنی بر پرامیسها هست. یعنی نتیجهٔ درخواستهایی که با اون میفرستیم رو میتونیم به شکل پرامیسها مدیریت کنیم. توی این مثال میخوایم به یک یک درخواست Ajax بزنیم و نتیجه رو به کاربر نشون بدیم:
با زدن دکمه ► میبینیم که ابتدا Axios به صفحه اضافه میشه و بعد با استفاده از اون، درخواستی به آدرس مد نظرمون میزنیم تا اطلاعات رو به کاربر نشون بدیم. توی این برنامه ۲ بار از پرامیسها استفاده کردیم 👌💯
خب دوستان این قسمت هم به پایان رسید و امیدوارم استفاده کرده باشید. برای ادامه آموزش به قسمتهای بعدی برین. روزتون خوش 😉 🌹