آموزش Async/Await جاوا اسکریپت – Async چیست؟

توسعه دهندگان جاوا اسکریپت بیشترین زمان را برای فراخوانی هنگام کار با کد های ناهمگام (asynchronous) صرف می کنند. در نتیجه بسیاری از ما جهنم callback را تجربه کرده ایم و این وحشت زمانی اتفاق می افتد که چیزی شبیه این اتفاق بیافتد.

خوشبختانه متد then اضافه شد. این جایگزین بسیار سازمان یافته تری نسبت به callback ها هستند. و بیشتر جامعه برنامه نویسان سریعا به آنها روی آوردند.

حال با توجه به  آخرین متمم از async/await ، نوشتن کدهای جاوا اسکریپت بهتر و راحت تر هم شده  است.

Async/Await چیست؟

Async/Await یکی از خصوصیات پیش بینی شده جاوا اسکریپت است تا کار با توابع ناهمگام را لذت بخش تر ، آسانتر و قابل درک تر سازد.  همچنین با تمام API های موجود  برپایه نتیجه بازگشتی سازگار است.

این نام از  کلمات async  و await ساخته شده که این دو کلمه کلیدی در تمیز نگه داشتن کد های ناهمگام کمک می کنند:

Async با تعریف تابع ناهمگام

(async function نام تابع(){...}).
  • تابع معمولی بطور خودکار به تابع بازگشتی تبدیل می شود.
  • زمانی که تابع Async فراخوانی می شود، پس از اجرا و پردازش  مقدار بازگشتی را به همراه محتویات Body برمی گرداند.
  • توابع Async قادر به استفاده از await هستند

Await –  اجرای Async را متوقف می کند

functions. (var result = await someAsyncCall();).
  • زمانی که Await  قبل از دستور فراخوانی بازگشتی  قرار میگیرد ، بقیه کد ها غیرفعال شده تا اجرای دستور بازگشتی  بدست آمدن نتیجه ی آن منتظر می مانند.
  • Await فقط قبل از دستور بازگشتی اجرا می شود، این دستور در callback اجرا نمی شود.
  • Await فقط داخل تابع async استفاده می شود.

مثال : فرض کنید می خواهیم یک فایل JSON را از سرورمان دریافت کنیم. باید تابعی نوشت تا  با استفاده از کتابخانه axios  یک درخواست HTTP GET به ادرس https:/mysite.com/misc/files/example.json بفرستد. حال باید منتظر پاسخ سرور باشیم، طبیعتا این درخواست ناهمگام خواهد بود.

در کد زیر می توان عملکرد مشابهی را دوبار ببینید.  بار اول در مقدار بازگشتی، و بار دوم هنگام استفاده از Async/Await  :

// Promise approach

function getJSON(){

    // To make the function blocking we manually create a Promise.

    return new Promise( function(resolve) {

        axios.get('https://mysite.com/misc/files/example.json')

            .then( function(json) {



                // The data from the request is available in a .then block

                // We return the result using resolve.

                resolve(json);

            });

    });



}


// Async/Await approach


// The async keyword will automatically create a new Promise and return it.

async function getJSONAsync(){



    // The await keyword saves us from having to write a .then() block.

    let json = await axios.get('https://mysite.com/misc/files/example.json');



    // The result of the GET request is available in the json variable.

    // We return it just like in a regular synchronous function.

    return json;

}

این کد تمیز و زیباست، زیرا کدی که با Async/Await نوشته شود، بسیار کوتاه تر وخوانایی بیشتری دارد.به غیر از نحو استفاده شده (syntax) این دو کد هیچ فرقی باهم ندارند و یکسان هستند.

تابع async  را به شکل زیر می توان فراخوانی کرد:

getJSONAsync().then( function(result) {

    // Do something with result.

});

آیا Async/Await توابع بازگشتی را منسوخ کرده است؟

پاسخ منفی است، در واقع  هنگام کار با Async/Await از توابع بازگشتی استفاده می شود.  درک درست از توابع بازگشتی در بلند مدت به شما کمک خواهد کرد و بسیار توصیه می شود.

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

یکی از این سناریوها زمانی اتفاق می افتد که ما نیاز به چندین فراخوانی مستقل نامتقارن داشته باشیم و منتظر بمانیم تا تمام آنها پایان یابد.

async function getABC() {

  let A = await getValueA(); // getValueA takes 2 second to finish

  let B = await getValueB(); // getValueB takes 4 second to finish

  let C = await getValueC(); // getValueC takes 3 second to finish



  return A*B*C;

}

 

هر await  منتظر فراخوانی نتیجه قبلی است. از آنجا که در هر زمان فقط یک فراخوانی می توان انجام داد ، کل توابع 9 ثانیه زمان  لازم دارند(2+4+3).

این کار ، روش سودمندی نیست زیرا 3 متغیر a، b و c  به همدیگر وابسته نیستند. به بیان دیگر ما نیازی به دانستن مقدار a قبل از b نداریم. می توان مقدار همه سه متغیر را در یک زمان بدست آورد و زمان کمتری از دست داد.

برای ارسال تمام درخواست ها در یک زمان به تابع ()Promise.all نیاز داریم . این کار باعث میشود که مطمئن شویم تمام نتایج را قبل از ادامه کار بدست می آوریم ، فراخوانی ناهمگام بطور موازی خواهد بود ، نه پشت سر هم.

async function getABC() {

  // Promise.all() allows us to send all requests at the same time.

  let results = await Promise.all([ getValueA, getValueB, getValueC ]);



  return results.reduce((total,value) => total * value);

}

 

این روش زمان کمتری را مصرف خواهد کرد. فراخوانی getValueA و getValueC زمانی تمام خواهند شد که فراخوانی getValueB تمام می شود.

به جای جمع زمان های سپری شده ،  زمان اجرا را از کند ترین درخواست کم می کنیم (getValueB – 4 seconds).

مدیریت خطا در Async/Await

یکی از ویژگی های عالی Async/Await  این است که می توانیم خطاهای غیر منتظره را با ساختار try/catch شناسایی کنیم. برای اینکار، چیدمان فراخوانی await را به صورت زیر طراحی می کنیم:

async function doSomethingAsync(){

    try {

        // This async call may fail.

        let result = await someAsyncCall();

    }

    catch(error) {

        // If it does we will catch the error here.

    } 

}



 

شرط catch  خطاهایی را که توسط فراخوانی ناهمگام که منتظر مانده یا هر کد ناقصی که داخل بلاک try نوشته ایم ، مدیریت می کند.

در صورت نیاز، هنگام اجرای  تابع async  نیز خطایابی میسر است. زیرا توابع async  مقداری را به عنوان مقدار بازگشتی برمی گردانند ،بنابراین می توان با استفاده از ()catch. مدیریت خطا، آن ها را فراخونی کنیم.

// Async function without a try/catch block.

async function doSomethingAsync(){

    // This async call may fail.

    let result = await someAsyncCall();

    return result; 

}


// We catch the error upon calling the function.

doSomethingAsync().

    .then(successHandler)

    .catch(errorHandler);

 

انتخاب روش مدیریت خطا بسیار مهم است. استفاده از هر دو روش try/catch و ()catch.  در یک زمان احتمالا منجر به مشکلات خواهد شد.

پشتیبانی مرورگر ها از Async/Await

Async/Await  در بیشتر مرورگر ها بجز IE11 دردسترس است.

نویسنده مطلب
سمیرا عظیمی

مهندسی نرم افزار خوندم و برنامه نویس هستم. عاشق رباتیک و نجوم و برنامه نویسی هستم.

دیدگاه کاربران

  • ali
    6 سال, 7 ماه پیش
    عالی بودهم ترجمه و هم مطالب ساده و روان

این وب سایت متعلق است به آذین وب (طراحی سایت در اصفهان) و تمامی حقوق آن محفوظ است.

طـبق ماده 12 فصل سوم قانون جرائم رایانه ای هرگونه کپی برداری از قالب پیگرد قانونی دارد.