Async در جاوا اسکریپت چیست؟‌ – به زبان ساده + نمونه کد

۱۶۸ بازدید
آخرین به‌روزرسانی: ۱۳ آبان ۱۴۰۲
زمان مطالعه: ۱۵ دقیقه
Async در جاوا اسکریپت چیست؟‌ – به زبان ساده + نمونه کد

سرآشپزی را تصور کنیم که در رستورانی بزرگ مشغول به کار است. در این رستوران هم‌زمان، سرآشپز با دقت غذایی را در زمانی معین آماده می‌کند و منتظر می‌ماند تا پخت این غذا تمام شود و سپس به دنبال پختن غذای بعدی می‌رود. این روش، روشی کند است و امکان دارد مشتریان از این رستوران رضایت نداشته باشند. این مسئله را می‌توان به async در جاوا اسکریپت یا ناهمزمانی تعمیم داد. در آشپزخانه ستورانی ناهم‌زمان سرآشپز تبدیل به استادی چندوظیفه‌ای می‌شود که چندین غذا را به طور هم‌زمان سرو می‌کند و به طور دوره‌ای پیشرفت پخت‌وپز آن‌ها را بررسی و تنظیم می‌کند.

این رویکرد تضمین می‌کند که سفارشات به سرعت انجام می‌شوند و اطمینان حاصل خواهد کرد که مشتریان غذای خود را در سریع‌ترین زمان ممکن دریافت کنند. به طور مشابه، در حوزه برنامه‌ نویسی، تکنیک‌های ناهم‌زمان نرم‌افزار را قادر می‌سازد تا چندین کار را هم‌زمان انجام دهد و منجر به اجرای سریع‌تر و کارآمدتر شود. جاوا اسکریپت، در هسته خود، «تک‌رشته‌ای» (Single Thread) است، به این معنی که خط خاصی از کد را در زمانی معین پردازش می‌کند. این طراحی می‌تواند مزایای عملکردی را با بهینه‌سازی استفاده از منابع ارائه دهد اما همچنین می‌تواند در هنگام مقابله با وظایف پیچیده‌ای که اجرای موازی را می‌طلبد، به نوعی محدودیت تبدیل شود. در این مطلب از «مجله فرادرس» async در جاوا اسکریپت را مورد بررسی قرار داده و به جنبه‌های ناهم‌زمانی جاوا اسکریپت خواهیم پرداخت.

async در جاوا اسکریپت چیست؟

جاوا اسکریپت ناهم‌زمان (ناهمگام | Asynchronous) به قابلیت جاوا اسکریپت برای ادامه عملیات خود بدون انتظار برای اتمام کار خاصی مربوط می‌شود. این ویژگی در زبان برنامه نویسی جاوا اسکریپت اجازه می‌دهد تا کدهای دیگر در حالی که در انتظار تکمیل کار ذکر شده است، اجرا شوند. توجه به این نکته مهم است که جاوا اسکریپت تک‌رشته‌ای است. این بدان معنی بوده که وظایف ناهم‌زمان به وسیله صف برگشتی و حلقه رویداد مدیریت می‌شوند.

در پارادایم جاوا اسکریپت «هم‌زمان» (همگام | Synchronous)، توابع به صورت متوالی و یکی پس از دیگری اجرا می‌شوند و هر کدام منتظر پایان عملیات قبلی هستند تا به عملیات بعدی بروند. در این حالت، کد از بالا به پایین به صورت خطی جریان می‌یابد.

تصویری برای نمایش نحوه انجام کارهای ناهمزمانی در جاوا اسکریپت

ماهیت برنامه نویسی async در جاوا اسکریپت

همان‌طور که قبلاً توضیح داده شد، جاوا اسکریپت، در هسته خود، به عنوان نوعی زبان تک‌رشته‌ای با زمینه اجرای جهانی عمل می‌کند. این نوع طراحی جاوا اسکریپت را ذاتاً هم‌زمان کرده و از «پشته» (Stack) فراخوانی برای اجرای کد به شیوه‌ای «آخرین ورودی، اولین خروجی» (LIFO) استفاده می‌کند. به عبارت ساده‌تر، async در جاوا اسکریپت به ترتیبی از اجرای متوالی پایبند است که در آن توابع یکی پس از دیگری، به ترتیبی که در آن فراخوانی می‌شوند پردازش خواهند شد. برای درک مفهوم جاوا اسکریپت همزمان، قطعه کد زیر را در نظر بگیرید:

1// Synchronous JavaScript
2console.log("synchronous.");
3console.log("synchronous javascript!");
4console.log("synchronous again!");

هنگامی که این کد اجرا می شود، خروجی به صورت زیر است:

// Output
"synchronous"
"synchronous javascript!"
"synchronous again!"

مثال فوق به وضوح نشان می‌دهد که جاوا اسکریپت هم‌زمان به صورت خطی پیشرفت کرده و برنامه کد را به ترتیب دقیق نوشته شده اجرا می‌کند.

چرا برنامه نویسی async در جاوا اسکریپت نیاز است؟

برنامه نویسی async در جاوا اسکریپت بسیار ضروری است زیرا چندین فرآیند را قادر می‌سازد تا بدون ایجاد اختلال در رشته اصلی به طور هم‌زمان اجرا شوند. این مسئله بسیار مهم است زیرا رشته اصلی به عنوان ساختار داده‌ای که دنباله فعلی فراخوانی‌های تابع را حفظ می‌کند، مسئول مدیریت پشته تماس است. هنگامی‌که رشته اصلی مسدود می‌شود، منجر به کاهش عملکرد خواهد شد. از سوی دیگر، برنامه‌نویسی ناهمزمان تضمین می‌کند که رشته اصلی بازمی‌ماند و اجازه می‌دهد تا در حین انجام عملیات ناهمزمان، کارهای اضافی اجرا شوند.

نمونه‌ای از برنامه نویسی همزمان در جاوا اسکریپت را می‌توان در تابع setTimeout()‎ یافت. این تابع اجرای کد جاوا اسکریپت را پس از مدت زمان مشخصی فعال می‌کند. پس از سپری شدن بازه زمانی تعیین شده، کد را یک بار اجرا می‌کند. برای استفاده از قدرت تابع setTimeout()‎ در جاوا اسکریپت، از توابع پیکان معرفی شده در «جاوا اسکریپت ES6» استفاده خواهد شد. این فراخوانی تابع دو پارامتر حیاتی دارد:

  • تابع: تابعی که یک بلوک از کد را کپسوله می‌کند.
  • میلی‌ثانیه: تأخیر زمانی قبل از اجرای تابع است.

برای درک بهتر این فرایند قطعه کد زیر مد نظر است:

1console.log("asynchronous.");
2setTimeout(() => console.log("asynchronous javascript!"), 3000);
3console.log("asynchronous again!");

برخلاف مثال قبلی ، کد بالا به صورت هم‌زمان در موتور جاوا اسکریپت اجرا نمی‌شود و این بار خروجی به صورت زیر خواهد بود:

1// asynchronous.
2// asynchronous again!
3// asynchronous javascript!

در اینجا تفکیک قطعه کد بالا به صورت زیر آمد است:

  • مرحله ۱: خط اول بلافاصله اجرا و asynchronous در کنسول ثبت می‌شود.
  • مرحله ۲: متد setTimeout()‎ فراخوانی می‌شود که تابع ناشناس را پس از ۳ ثانیه تأخیر (۳۰۰۰ میلی‌ثانیه) برای اجرا برنامه‌ریزی می‌کند. تابع ناشناس setTimeout()‎ به کنسول وارد خواهد شد.
  • مرحله ۳: خط سوم اجرا می‌شود و synchronous again به کنسول وارد خواهد شد.
  • مرحله ۴: پس از ۳ ثانیه، تابع ناشناس برنامه‌ریزی شده قبلی از متد setTimeout()‎ اجرا می‌شود و asynchronous javascript را ثبت می‌کند.

در اصل جاوا اسکریپت ناهمزمان قبل از ادامه اجرای توابع بعدی منتظر پاسخ نمی‌ماند. این رفتار برای برنامه‌هایی که به قدرت پردازش قابل‌توجهی نیاز دارند بسیار سودمند است و باعث می‌شود چندین کار به طور هم‌زمان پیشرفت کنند.

تکنیک های برنامه نویسی جاوا اسکریپت ناهمزمان

جاوا اسکریپت تکنیک‌های مختلفی را برای کار با عملیات ناهمزمان ارائه می‌دهد که به کاربر امکان خواهد داد جریان کد خود را به طور مؤثر مدیریت و کنترل کند.

رویکردهای برنامه نویسی ناهمزمان در جاوا اسکریپت به صورت زیر هستند:

  • Callbacks : Callbacks کاربر را قادر می‌سازد تا کدهای ناهمزمان را به شیوه‌ای ساختاریافته‌تر و مشابه توابع همزمان بنویسد. آن‌ها شامل انتقال توابع به عنوان آرگومان به توابع دیگر هستند که پس از تکمیل یک کار خاص اجرا می‌شوند.
  • Promises  : Promises در جاوا اسکریپت که به عنوان وعده در جاوا اسکریپت از آن یاد می‌شود، فرآیند نوشتن کد جاوا اسکریپت ناهمزمان را ساده می‌کند. آن‌ها روشی منطقی برای رسیدگی به عملیاتی ارائه می‌دهند که باید پس از زمان از پیش تعریف‌شده یا زمانی که شرایط خاصی برآورده می‌شود، رخ دهد. Promises نوعی رویکرد ساختاریافته برای مقابله با عملیات ناهمزمان ارائه می‌دهد.
  • Async/Await : Async/await در زبان برنامه نویسی جاوا اسکریپت نوعی افزودنی نسبتاً جدید به جاوا اسکریپت است که به خوانایی و مختصرنویسی کدهای ناهمزمان کمک می‌کند. این ویژگی به کاربر امکان می‌دهد کدی بنویسد که پس از مدت زمان مشخص یا زمانی که شرایط خاص به روشی ساده‌تر و شهودی انجام می‌شود اجرا شود. Async/wait در جاوا اسکریپت بر اساس وعده‌ها استوار است و روشی مدرن و عالی برای مدیریت عملیات ناهمزمان ارائه می‌دهد.
یک برنامه نویس کامپیوتر در حال برنامه نویسی ناهمزمان در جاوا اسکریپت

مفهوم Callbacks در ناهمزمانی

توابع جاوا اسکریپت فوق‌العاده متنوع هستند و می‌توانند به عنوان آرگومان به توابع دیگر منتقل شوند. این ویژگی منحصربه‌فرد امکان ایجاد «توابع برگشت تماس» ( Callbacks ) را فراهم می‌کند که توابعی هستند که پس از تکمیل تابعی بیرونی اجرا می‌شوند. فراخوان‌ها به عنوان ورودی برای عملکردهای دیگر ارائه شده و فراخوانی تابعی به وسیله دیگری را تسهیل می‌کنند. مثال زیر این مفهوم را بیان می‌کند:

1function incrementDigits(callback) {
2    callback();
3}

در قطعه کد فوق تابع incrementDigits() تابع دیگری را به عنوان پارامتر می‌پذیرد و متعاقباً آن را فراخوانی می‌کند. در جاوا اسکریپت، این عمل معمولاً به عنوان استفاده از تابع پاسخ به تماس شناخته می‌شود. تابعی که به عنوان آرگومان به تابع دیگری ارسال می‌شود و در اصل نوعی تابع فراخوانی است. فراخوان‌ها به طور گسترده در جاوا اسکریپت برای انجام اقدامات ناهم‌زمان مانند رسیدگی به درخواست‌های «آجاکس» «AJAX» یا پاسخ دادن به تعاملات کاربر استفاده می‌شوند. با تکیه‌بر مفاهیم ارائه شده از قبل در مورد تابع setTimeout ()  فراخوانی‌ها را می‌توان به عنوان «توابع پیکان» (Arrow Functions) ES6، به عنوان سینتکسی مدرن‌تر از تابع جاوا اسکریپت نوشت:

1setTimeout(() => {
2    console.log("Output initiated after 5 seconds");
3}, 5000);

در مثال بالا، متد setTimeout () برای به تأخیر انداختن اجرای تابع استفاده می‌شود و رشته Output initiated after 5 seconds را با استفاده از تابع پیکان به عنوان پاسخ به تماس، به کنسول ثبت می‌کند. تأخیر مشخص شده ۵۰۰۰ میلی‌ثانیه یا ۵ ثانیه است. هنگامی‌که عملیات ناهم‌زمان به پایان رسید، تابع Callbacks فراخوانی می‌شود و نتیجه را مدیریت می‌کند. در زیر مثال پیچیده‌تری از این مفهوم آورده شده است:

1function incrementDigits(num, callback) {
2    setTimeout(function() {
3        num++;
4        console.log(num);
5        if (num < 10) {
6            incrementDigits(num, callback);
7        } else {
8            callback();
9        }
10    }, 1000);
11}
12
13incrementDigits(0, function() {
14    console.log('Done!');
15});

کد فوق نوعی تابع بازگشتی را نشان می‌دهد که تا زمانی که عدد به مقداری بیشتر از ۱۰ برسد، خود را فراخوانی می‌کند. در آن نقطه، اجرای تابع Callbacks ارائه شده را آغاز خواهد کرد. همچنین تابع setTimeout () تأخیری را معرفی کرده و فرآیند طولانی‌تری را شبیه‌سازی می‌کند. این تابع به صورت تدریجی هر عدد را چاپ خواهد کرد. به این ترتیب که از ۰ شروع می‌شود و تا رسیدن به ۱۰ این عملیات ادامه می‌یابد و در آخر Done را نمایش می‌دهد. کد فوق به صورت ناهم‌زمان عمل می‌کند و به توابع اجازه می‌دهد تا به طور هم‌زمان، بدون انتظار برای تکمیل یکدیگر اجرا شوند.

یک دختر برنامه نویس در حال انجام کارهای برنامه نویسی Async در جاوا اسکریپت

مکانیسم توابع ناهم‌ زمان و فراخوانی

هنگامی‌که با توابع ناهم‌زمان یا async در جاوا اسکریپت سروکار داریم، عملکرد این توابع را می‌توان با بررسی مکانیسم‌های اصلی آن‌ها درک کرد. در زیر توضیحات کاملی از این توابع برای درک بهتر این موضوع ارائه شده است:

  • «توابع و انتظارات ناهمگام» (Async Functions and Awaits): توابع ناهم‌زمان از کلمه کلیدی await استفاده می‌کنند که به طور موقت اجرا را متوقف می‌کند تا زمانی که وعده مرتبط حل شود. این بدان معنی است که عملکرد اساساً تا زمانی که عملیات ناهم‌زمان با موفقیت کامل شود متوقف می‌شود. به عبارت دیگر، await به کاربر این امکان را می‌دهد که توابع ناهم‌زمان را به‌گونه‌ای بنویسد که متوالی یا هم‌زمان به نظر می‌رسد.
  • «تماس‌های ناهم‌زمان» (Asynchronous Callbacks): پاسخ به تماس ناهم‌زمان نوعی تابع مرتبه بالاتر محسوب می‌شود که برای اجرای عملکرد پاسخ به تماس ناهم‌زمان داخلی خود به صورت غیر مسدود کننده طراحی شده است. هنگامی‌که تابع ناهم‌زمان تابع Callbacks را فراخوانی می‌کند، در حالی که منتظر تکمیل تماس است، اجرای آن را متوقف نمی‌کند. در عوض، در حالی که تماس برگشتی مستقل عمل می‌کند، به عملیات خود ادامه می‌دهد. در شرایطی که توابع Callbacks  تودرتو باشند معمولاً منجر به چیزی می‌شود که به آن callback hell یا جهنم تماس می‌گویند.

همچنین تکنیک‌هایی برای مدیریت و ساده کردن کد وجود دارد که در زیر به آن‌ها اشاره شده است:

  • «استفاده از Promise»: برای هر تابع Callbacks ، می‌توان نوعی وعده مربوطه ایجاد کرد. اگر عملیات برگشت تماس با موفقیت انجام شود، وعده به سرانجام می‌رسد یا به‌اصطلاح حل می‌شود. اگر شکست بخورد، وعده مردود است. این روش به ساختار کد ناهم‌زمان و مدیریت مؤثرتر وظایف ناهم‌زمان کمک می‌کند.
  • «اجرای Async/Await»: با استفاده از async/wait  ، توابع ناهم‌زمان را می‌توان به صورت متوالی هماهنگ کرد. اجرا در نقاطی که انتظار به کار می‌رود تا زمانی که وعده مرتبط با موفقیت به سرانجام برسد، متوقف می‌شود. این رویکرد خوانایی کد را افزایش می‌دهد و مدیریت عملیات ناهم‌زمان را با نشان دادن آن‌ها به‌گونه‌ای که گویی به صورت متوالی اجرا می‌شوند، ساده می‌کند.

Promises در جاوا اسکریپت

در قلمرو جاوا اسکریپت ناهم‌زمان، وعده یا Promises نوعی ساختار قدرتمند محسوب می‌شود که نماد موفقیت یا شکست نهایی عملیات ناهم‌زمان به‌عنوان یک شی جاوا اسکریپت است. وعده‌ها برای تسهیل ایجاد کد ناهم‌زمان طراحی شده‌اند که به شیوه‌ای شبیه به عملیات هم‌زمان در جاوا اسکریپت عمل می‌کنند. در زمینه مورد بحث در این مطلب، وعده به معنای کاری است که تکمیل آن مدتی طول می‌کشد.

وعده می‌تواند در یکی از سه حالت زیر وجود داشته باشد، در حال انتظار، محقق شده یا رد شده.

  • در حال تعلیق یا انتظار: عملیات ناهم‌زمان یا async در جاوا اسکریپت هنوز در حال انجام بوده در حالی که وعده انجام نشده باقی‌مانده است.
  • برآورده شد یا محقق شده: تحقق وعده بیانگر تکمیل موفقیت‌آمیز عملیات ناهم‌زمان است.

برای ایجاد وعده، می‌توان از سازنده Promises مانند کد زیر استفاده کرد:

1let promise = new Promise(function(resolve, reject) {
2    // Logic for resolving or rejecting the promise goes here
3});

تشریح کد بالا به صورت زیر است:

  • Promise Constructor : سازنده Promises نوعی شی جاوا اسکریپت داخلی بوده که آرگومانی واحد را می‌گیرد که نوعی تابع است. از این تابع به‌ عنوان تابع اجرا کننده یا Executor Function یاد می‌شود.
  • Executor Function : این تابع هسته اصلی وعده است. این تابع آنچه را که وعده انجام خواهد داد، از جمله هرگونه عملیات ناهم‌زمان را مشخص می‌کند. Executor Function دو پارامتر حل ( resolve ) و رد کردن ( reject ) را دریافت می‌کند که توابعی هستند که می‌توان با فراخوانی نشان داد که آیا وعده باید حل شود یا رد شود.
  • فراخوانی خودکار: نیازی نیست کاربر خودش تابع اجراکننده را فراخوانی کند. هنگامی که وعده جدید ایجاد می‌شود، به طور خودکار به وسیله جاوا اسکریپت فراخوانی می‌شود. تابع Executor Function بلافاصله پس از ایجاد وعده اجرا می‌شود و شروع به پردازش منطق سفارشی کاربر می‌کند.
تصویری برای نمایش وعده ها و نحوه به سر انجام رسیدن آن ها در جاوا اسکریپت

در اینجا روند ایجاد promise آورده شده است.

  • مرحله ۱: وعده جدید با استفاده از سازنده وعده ایجاد می‌شود، که با دو آرگومان تکمیل می‌شود: حل کردن و رد کردن.
  • مرحله ۲: سپس می‌توان از متد .then() در وعده استفاده کرد. این متد دو تابع فراخوانی را می‌پذیرد، یکی برای رسیدگی به‌وضوح وعده و دیگری برای رسیدگی به رد وعده.
  • مرحله ۳: اولین تابع فراخوانی زمانی اجرا می‌شود که وعده با موفقیت حل شود، که با فراخوانی تابع resolve مشخص می‌شود. در مقابل، تابع برگشت فراخوان دوم موقعیت‌هایی را مدیریت می‌کند که در آن وعده رد می‌شود، که نشان‌دهنده شکست عملیات ناهم‌زمان است.

به طور خلاصه، وعده‌ها نقشی محوری در ساده‌سازی مدیریت عملیات ناهم‌زمان ایفا می‌کنند. در بخش بعد از مطلب async در جاوا اسکریپت، نحوه تبدیل callback به Promises بحث خواهد شد.

تبدیل callback به promise در جاوا اسکریپت

هنگام انتقال از callback به وعده، مرحله اولیه شامل ایجاد نوعی شی وعده جدید است. سازنده وعده با استفاده از دو آرگومان ضروری در این میان ظاهر می‌شود آن هم توابع با پارامترهای resolve و Reject هستند. هنگامی‌که عملیات ناهم‌زمان با موفقیت انجام می‌شود، تابع resolve در اصل فراخوانی خواهد شد. از طرف دیگر هنگامی‌که عملیات با مشکل یا شکست مواجه می‌شود، تابع Reject فراخوانی خواهد شد. در چنین سناریویی منطق «برگشت تماس» ( callback ) در این تابع تعبیه شده است و نتیجه عملیات تعیین می‌کند که آیا وعده به سر انجام برسد یا خیر.

شی وعده پس از اجرای فراخوان بازگردانده می‌شود و آن را برای پردازش بعدی در دسترس قرار می‌دهد. با تبدیل تماس‌های برگشتی به وعده، توسعه‌دهندگان می‌توانند کدی را تولید کنند که مختصرتر و قابل‌فهم‌تر باشد. نمونه کد زیر نحوه انتقال از تابع callback به وعده را نشان می‌دهد:

1const incrementDigits = num => {
2    return new Promise((resolve, reject) => {
3        setTimeout(() => {
4            num++;
5            console.log(num);
6            if (num < 10) {
7                resolve(incrementDigits(num));
8            } else {
9                resolve('done!');
10            }
11        }, 1000);
12    });
13};
14
15incrementDigits(0).then(res => console.log(res));

کد بالا از وعده‌هایی برای اجرای عملیات ناهم‌زمان یا یا async در جاوا اسکریپت استفاده می‌کند. در اصل کد فوق تکنیکی به نام «زنجیره وعده» (Promise Chaining)، به عنوان راه‌حلی مناسب برای رسیدگی به عوارض مرتبط با callback hell ارائه خواهد کرد. با خطوط کمتر کد و رویکرد ساده‌تر، این روش امکان بازیابی متوالی داده‌ها از منابع متعدد فراهم می‌کند. در این مثال، تابع incrementDigits() ایجاد می‌شود که نوعی آرگومان عددی می‌گیرد. همچنین در این میان نوعی وعده جدید شکل خواهد گرفتو دو آرگومان اساسی دریافت می‌کند. این دو آرگومان هر دو تا تابع هستند و همان‌طور که بیان شد، resolve و Reject نام دارند.

برنامه نویس کامپیوتر پشت لپ تاپ در حال برنامه نویسی

مراحل بعدی مستلزم تأخیر یک‌ثانیه‌ای است که مقدار num را یک‌بار افزایش می‌دهد، مقدار به‌روز شده num را ثبت می‌کند و اگر num کمتر از ۱۰ باشد، وعده را به سرانجام می‌رساند و این در حالی است که تابع را مجدداً با num به عنوان آرگومان فراخوانی می‌کند. اگر num از ۱۰ بیشتر شود، وعده محقق می‌شود و رشته done ثبت خواهد شد. در نهایت، وعده فراخوانی و نتیجه ثبت می‌شود. برای مدیریت وعده و بازیابی نتیجه عملیات ناهم‌زمان incrementDigits() ، از متد .then() استفاده می‌شود. در صورت بروز خطا در وعده، با فراخوانی تابع reject() با خطایی، وعده رد خواهد شد. برای رسیدگی به چنین وعده‌هایی که رد شده‌اند، می‌توان با استفاده از تابع .catch نوعی تماس برگشتی را به کد پیوست کرد.

متدهای مدیریت وعده در جاوا اسکریپت

متدهای کنترل‌کننده وعده به‌عنوان ابزاری ضروری برای برقراری ارتباط بین توابع «اجرایی» (Executor) و  توابع «مصرف‌کننده» (Consumer) عمل می‌کنند و با استفاده از آن‌ها از همگام‌سازی زمانی که وعده حل یا رد می‌شود، اطمینان حاصل می‌کنند. این متدها کنترل‌کننده مدیریت عملیات ناهم‌زمان را با کپسوله کردن داده‌ها در شی به‌جای برگرداندن صرفاً نوعی مقدار، تسهیل خواهند کرد. متدهای کنترل‌کننده وعده اولیه به صورت موارد زیر هستند:

  • .then() : این متد به کاربر اجازه می‌دهد تا مشخص کند وقتی وعده با موفقیت حل شد چه اتفاقی باید بیفتد. این متد در اصل نوعی تابع callback برای رسیدگی به مقدار حل شده ارائه می‌دهد و کاربر را قادر می‌سازد تا پس از تحقق وعده، جریان اجرا را ادامه دهد.
  • .catch : هنگامی‌که وعده با خطا مواجه یا رد می‌شود، متد .catch وارد عمل خواهد شد. این متد به کاربر امکان می‌دهد نحوه رسیدگی به توابع رد یا rejection را با استفاده از سازوکارهایی مانند راهبردهای مدیریت خطا و بازیابی، انجام دهد.
  • .finally() : متد .finally() برای تعیین اقداماتی که باید انجام شوند، صرف‌نظر از اینکه وعده حل شده یا رد شده است، استفاده می‌شود. این متد اغلب برای کارهای پاک‌سازی که باید بدون توجه به نتیجه وعده اجرا شوند، استفاده می‌شود.

علاوه بر این متدهای کنترل‌کننده اولیه، متدهای کنترل‌کننده وعده‌های مفید دیگری نیز وجود دارد که به صورت موارد زیر هستند و کاربرد کمتری نسبت به متدهای بالا دارند.

  • .all() : این متد نوعی وعده واحد ایجاد می‌کند که تنها زمانی حل می‌شود که تمام وعده‌های آرایه‌ای خاص با موفقیت انجام شود. این متد در اصل زمانی مفید است که قبل از ادامه، باید منتظر ماند تا چندین عملیات ناهم‌زمان کامل شوند.
  • .race() : متد Race() نوعی وعده واحد ایجاد می‌کند که به‌محض رفع یا رد شدن یکی از وعده‌های آرایه رفع یا رد می‌شود. این متد زمانی که کاربر بخواهد به‌محض تکمیل هر یک از عملیات ناهم‌زمان جریان برنامه ادامه یابد، بسیار مفید است.

این متدهای کنترل‌کننده وعده در برنامه نویسی async در جاوا اسکریپت برای ساختاردهی و مدیریت کدهای ناهم‌زمان مورد استفاده قرار می‌گیرند و به توسعه‌دهندگان اجازه می‌دهند تا برنامه‌های سازمان‌یافته‌تر، کارآمدتر و پاسخگوتر ایجاد کنند. مراحل بعدی مستلزم تأخیر یک ثانیه‌ای است که مقدار num را یک‌بار افزایش می‌دهد، مقدار به‌روز شده num را ثبت می‌کند و اگر num کمتر از ۱۰ باشد، وعده را به سرانجام می‌رساند و این در حالی است که تابع را مجدداً با num به عنوان آرگومان فراخوانی می‌کند. اگر num از ۱۰ بیشتر شود، وعده محقق می‌شود و رشته done ثبت خواهد شد. در نهایت، وعده فراخوانی و نتیجه ثبت می‌شود.

یک برنامه نویس در حال کدنویسی در اتاقای با بگ گراند برنامه نویسی

برای مدیریت وعده و بازیابی نتیجه عملیات ناهم‌زمان incrementDigits() ، از متد .then() استفاده می‌شود. در صورت بروز خطا در وعده، با فراخوانی تابع reject() با خطایی، وعده رد خواهد شد. برای رسیدگی به چنین وعده‌هایی که رد شده‌اند، می‌توان با استفاده از تابع .catch نوعی تماس برگشتی را به کد پیوست کرد.

Async/Await در جاوا اسکریپت

در بخش قبل، ایجاد تماس‌های غیرهمزمان بررسی شد. حال در این بخش به بررسی ترکیب قدرتمند Await و Async در جاوا اسکرییپت می‌پردازیم که کد ناهم‌زمان را به چیزی شبیه به اجرای هم‌زمان تبدیل می‌کند. این تکنیک کاربر را قادر می‌سازد تا کدی بنویسد تا طوری به نظر می‌رسد که به صورت متوالی پیشرفت کرده و در عین حال ماهیت ناهم‌زمان خود را حفظ می‌کند.

در جاوا اسکریپت Async/wait فرآیند نوشتن و درک کد شامل عملیات ناهم‌زمان را ساده می‌کند. Async/wait در واقع نوعی فناوری جاوا اسکریپت است که به کاربر امکان می‌دهد کدهای ناهم‌زمان را به سبکی هم‌زمان‌تر بنویسد. همان‌طور که آموخته‌ایم، زنجیره زدن وعده‌ها با هم می‌تواند سخت و پیچیده شود. Async/wait برای رفع این چالش‌ها معرفی شدند. در قطعه کد زیر نحوه تعریف توابع async در جاوا اسکریپت آمده است:

1// Async/Await
2const newAsyncFunc = async () => {
3
4};

در «توابع ناهمگام» (Async Functions)، کلمه کلیدی await برای سیگنال دادن به تابع برای توقف و منتظر چیزی استفاده می‌شود:

1const asyncFunc = async () => {
2    const result = await asyncFunc();
3    // Perform tasks here
4}

برای نشان دادن عملیات ناهم‌زمان، بیایید تابع incrementDigits() را با استفاده از توابع async و پارادایم Async/wait دوباره تصور کنیم:

1// Example using async/await
2const incrementDigits = async num => {
3    num++;
4    console.log(num);
5    if (num < 10) {
6        await incrementDigits(num);
7    } else {
8        return 'done!';
9    }
10};
11
12(async () => {
13    const res = await incrementDigits(0);
14    console.log(res);
15})();

در قطعه کد بالا، دستور Async/wait برای افزایش عدد مدنظر تا رسیدن به ۱۰ استفاده می‌شود. علاوه بر این، از کلمه کلیدی await برای توقف اجرای تابع incrementDigits() تا زمان تحقق وعده استفاده شده است. هنگامی‌که وعده حل شد یا به اصطلاح به سرانجام رسید، کد زیر بخش کلمه کلیدی await اجرا می‌شود که امکان ارائه نوعی رویکرد شهودی و متوالی‌تر را برای مدیریت عملیات ناهم‌زمان فراهم می‌کند.

رسیدگی به خطا در جاوا اسکریپت ناهمزمان

خطاها در جاوا اسکریپت ناهم‌زمان می‌توانند از منابع مختلفی از جمله اشتباهات کدنویسی، ورودی نادرست یا شرایط پیش بینی نشده ناشی شوند. برای مدیریت مؤثر این خطاها، از بلوک‌های try/catch استفاده خواهد شد. ساختار try/catch در جاوا اسکریپت برای شناسایی و رسیدگی به مشکلات احتمالی که ممکن است در طول فرآیند ناهم‌زمان رخ دهد به صورت زیر مورد استفاده قرار می‌گیرد:

1try {
2    // Code block to test for errors
3} catch (e) {
4    // Handle the error here
5}

تشریح ساختار فوق به صورت زیر است:

  • دستور try به کاربر این امکان را می‌دهد که بلوکی از کد را برای خطاها ارزیابی کند.
  • دستور catch برای مدیریت و پاسخگویی به آن خطاها استفاده می‌شود. مانند مثال زیر:
1try {
2    alert("This is an error function!");
3} catch (e) {
4    alert(e);
5}

با گنجاندن متد catch در پایان عملیات async در جاوا اسکریپت، می‌توان به طور مؤثری هر گونه خطای احتمالی را که ممکن است ایجاد شود، مدیریت کرد. بلوک catch می‌تواند پارامترهایی را بپذیرد که اطلاعات دقیق خطا را ارائه می‌دهند. به طور معمول، بلوک catch برای ثبت خطا یا نمایش پیام‌های خاص به کاربر استفاده می‌شود. اکنون، زمانی که تابع ناهم‌زمان incrementDigits() مجهز به تابع کنترل کننده خطا باشد، می‌توان از آن به صورت زیر استفاده کرد:

1const incrementDigits = async num => {
2    try {
3        num++;
4        console.log(num);
5        if (num < 10) {
6            await incrementDigits(num);
7        } else {
8            return 'done!';
9        }
10    } catch (err) {
11        console.log(err);
12    }
13};
14
15(async () => {
16    const res = await incrementDigits(0);
17    console.log(res);
18})();

در کد فوق، ساختار try/catch برای رسیدگی به خطاهای احتمالی در طول اجرای تابع ناهمزمان incrementDigits() استفاده می‌شود. اگر خطایی در بلوک try رخ دهد، بلوک catch اطلاعات خطا را برای عیب‌یابی و مدیریت مؤثر ثبت می‌کند.

مزایای جاوا اسکریپت ناهمزمان چیست؟

جاوا اسکریپت ناهم‌زمان بسیار روشی ارزشمند است، به ویژه هنگامی‌که شخص برنامه نویس با فرآیندهای فشرده منابع مانند درخواست‌های شبکه یا عملیات فایل دست‌وپنجه نرم می‌کند. با اجرای این وظایف به صورت ناهم‌زمان، کامپیوتر می‌تواند به پردازش سایر بخش‌های کد در حالی که منتظر نتایج است ادامه دهد، شاهکاری که نه‌تنها استفاده از منابع را افزایش می‌دهد، بلکه اجرا را نیز تسریع می‌کند. قلمرو برنامه نویسی ناهم‌زمان تنها به مدیریت منابع محدود نمی‌شود بلکه نقش مهمی در توسعه وب به معنای امروزی دارد. این فناوری جاوا اسکریپت به توسعه‌دهندگان این امکان را می‌دهد که به‌سرعت به تعاملات و رویدادهای کاربر بدون ایجاد مانع در پاسخگویی رابط کاربری پاسخ دهند.

یک برنامه نویس وب در حال کدنویسی با زبان جاوا اسکریپت برای انجام عملیات ناهمزمانی

تکنیک‌های برنامه‌ نویسی Async در جاوا اسکریپت در هماهنگی با برنامه‌های کاربردی وب مدرن کار می‌کنند و از بارگیری یکپارچه داده‌ها در پس‌زمینه اطمینان حاصل خواهند کرد که کاربران فعالانه با رابط تعامل دارند. این هم‌افزایی نوعی تجربه کاربری پاسخگو و همه‌جانبه را تضمین می‌کند. با افزایش «برنامه‌های تک‌صفحه‌ای» (SPA) و تقاضا برای تعامل روان با کاربر، اهمیت برنامه نویسی ناهم‌زمان در پیشرفتی مداوم است. در اصل برنامه نویسی ناهم‌زمان در جاوا اسکریپت مفهومی اساسی برای ایجاد برنامه‌های کاربردی وب پویا و جذاب در عصر دیجیتال است.

سخن پایانی

در مطلب جامع فوق از مجله فرادرس، به قلمرو جاوا اسکریپت ناهم‌زمان پرداختیم، پیچیدگی‌های آن را آشکار کرده و مکانیسم‌هایی را که عملکرد آن را هدایت می‌کنند را مورد بررسی قرار دادیم. همچنین در مطلب فوق ما چگونگی کار با جاوا اسکریپت ناهم‌زمان با استفاده از وعده‌ها را مورد بازبینی قرار داده و قدرت async/wait را بررسی کردیم.

در کنار این‌ها و در طول مسیر، بینش‌هایی در مورد اهمیت توابع callbacks  و نقش آن‌ها به عنوان توابع ساده که فقط پس از اتمام رویداد اجرا می‌شوند، به دست آوردیم. به امید اینکه مطلب فوق در رابطه با مفهوم Async در جاوا اسکریپت مورد رضایت کاربران عزیز قرار گرفته باشد.

بر اساس رای ۱ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
SemaPhoreci
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *