مقایسه callback - promise و async/await در جاوااسکریپت

مقایسه callback - promise و async/await در جاوااسکریپت

مقایسه callback - promise و async/await در جاوااسکریپت

Callbacks vs. Promises vs. Async/Awaits

توسط : admin
هنگام نوشتن یا اشکال زدایی کد ، ما معمولاً به این فکر می کنیم که چگونه مترجم آن کد را از بالا به پایین کل کد را ، خط به خط ، پردازش میکند . اکنون ، واقعاً این چیزی نیست که در زندگی واقعی اتفاق می افتد. مترجمان به مراتب پیچیده تر از این هستند ، اما طبق فرضیه ما می توانیم از این طریق به این روند فکر کنیم.

 

این امر در مورد کد همزمان (یا مسدود کننده) صدق می کند ، اما هنگام فکر کردن به سیستم ناهمزمان (یا غیر مسدود کننده) نیاز به کمی انعطاف در طرز فکر است. با توجه به اینکه Node.js یک محیط غیر مسدود کننده است ، بیایید عملیات async را تعریف کنیم و روش های مقابله با آن را در JavaScript و Node.js. ببینیم.

 

تفاوت بین کد نویسی Sync و Async

برای ساده کردن آن ، بیایید مثالی از زندگی واقعی بگیریم که احتمالاً بیش از حد برای توضیح تفاوت مورد استفاده قرار می گیرد.

هنگام تماس با مرکز خدمات مشتری ، آنها معمولاً مشغول کار هستند و شما باید برای  ثبت درخواست  در شروع کار صبر کنید تا پردازش ، درخواست شما را آزاد کند. شما برای چند دقیقه در آنجا می مانید و اگر خوش شانس باشید ، یک مأمور پس از آن به شما اختصاص داده میشود .

 

اما در سایر مراکز خدمات مشتری ، نام و شماره تلفن شما را برمی دارند و به شما می گویند که بعداً با شما تماس می گیرند. شما به زندگی خود و هر کاری که انجام می دادید ادامه می دهید تا زمانی که شما را برای پردازش درخواست شما فراخوانی کنند.

 

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

 

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

 

برخی از نمونه های کد async در JS و Node.js در هنگام استفاده از setTimeout و setInterval ، ارسال درخواست AJAX و عملیات I / O هستند.

 

روش های مختلفی برای مدیریت کد نویسی async وجود دارد.که شامل  callbacks ، promises ها ، و async/await در  ES2017 میباشند .

 

 

Callbacks

Callbacks فقط نام یک قرارداد برای استفاده از توابع JavaScript است. به جای اینکه بلافاصله نتیجه مانند بسیاری از توابع را برگردانید ، عملکردهایی که از callbacks استفاده می کنند مدتی طول می کشد تا نتیجه حاصل شود. بیایید مثالی بزنیم.

 

console.log("One"); 

setTimeout(() => { console.log("Two"); }, 500); 

console.log("Three");

 

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

One
Two
Three

 

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

One
Three
Two

 

پاسخ برگشتی تابعی است که به عنوان اولین آرگومان به setTimeout منتقل می شود و پس از گذشت 500 میلی ثانیه اجرا خواهد شد.

 

Node.js بر اساس این ایده ساخته شده است و پایه و اساس آن را می سازد.

یکی از اشکالات callbacks  همان چیزی است که به عنوان callback hell شناخته می شود. این اتفاق هنگامی می افتد  که یک callback ، داخل یک callback ، داخل یک callback دیگر ، و غیره وجود دارد. در اینجا مثالی از callbackhell.com آورده شده است.

fs.readdir(source, function (err, files) {
    if (err) {
        console.log('Error finding files: ' + err);
    } else {
        files.forEach(function (filename, fileIndex) {
            console.log(filename);
            gm(source + filename).size(function (err, values) {
                if (err) {
                    console.log('Error identifying file size: ' + err);
                } else {
                    console.log(filename + ' : ' + values);
                    aspect = (values.width / values.height);
                    widths.forEach(function (width, widthIndex) {
                    height = Math.round(width / aspect);
                    console.log('resizing ' + filename + 'to ' + height + 'x' + height);
                    this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
                        if (err) console.log('Error writing file: ' + err);
                    })
                    }.bind(this));
                }
            });
        });
    }
})

Promises ها برای نجات ما از این وضعیت وارد شدند .

 

Promises

هدف Promise نشان دهنده اتمام (یا عدم موفقیت) یک عمل غیر همزمان و مقدار حاصل از آن است. این یک پروکسی برای یک مقدار است که لزوماً در زمان ایجاد آن شناخته نشده است ، و نشان دهنده نتیجه آینده یک عملیات ناهمزمان است.

 

کد فراخوانی شده می تواند منتظر بماند تا آن promise قبل از اجرای مرحله بعدی تحقق یابد. برای انجام این کار ، promise دارای روشی به نام then است که عملکردی را می پذیرد که هنگام تحقق promise محقق می شود.

 

Promises ها از طریق ES2015 در جاوا اسکریپت بومی شدند ، اما ایده Promises ها پیش از این وجود داشت.

نحو دستور مانند زیر است :

 

new Promise(function(resolve, reject) { ... } );

بریم یک مثال عملی بزنیم .

let myFirstPromise = new Promise((resolve, reject) => {
    setTimeout(function(){
        resolve("Success!"); // fulfilled
    }, 250);
});

myFirstPromise.then((successMessage) => {
    console.log("Yay! " + successMessage);
});

 

در اینجا ما یک  نوع Promise ، با نام  myFirstPromise را تعریف می کنیم ، که یک arrow function را به عنوان مجری به عهده خواهد گرفت. setTimeout (...) شبیه سازی کد async است که می تواند چیزی شبیه به درخواست xhr باشد. وقتی کارهایی که به صورت ناهمزمان انجام می دادیم موفقیت آمیز بود ما (...)  resolve فراخوانی می کنیم  ، و هنگامی که شکست خورد آن  را reject(...) می کنیم. successMessage در then(...) همان چیزی است که ما در resolve(...) تصویب کردیم و لازم نیست رشته باشد ، اما اگر این فقط یک پیام موفقیت آمیز باشد ،نتیجه در خروجی نمایش داده خواهد شد .

 

ES2017's Async/Await

Promise ها بسیار بهتر از callbacks بودند و مشکلاتی را که callbacks  معرفی کرده بودند را حل می کردند اما هنوز این نوع روش غیر طبیعی برای برخورد با کد async را داشتند. فقط  async/await است  که به توسعه دهنده اجازه می دهد تا با کد async را بطور طبیعی و بدون هیچگونه مشکلی پیاده سازی کند .

هنگامی که یک عملکرد async فراخوانی می شود ، یک Promise را برمی گرداند. هنگامی که تابع async یک مقدار را برمی گرداند ،  Promise با resolved می شود. هنگامی که عملکرد async استثنا یا مقداری را پرتاب می کند ، Promise با مقدار rejected  رد می شود.

 

یک عملکرد async می تواند حاوی یک عبارت await باشد ، که باعث متوقف شدن عملکرد تابع async شده و منتظر نتیجه  Promise می میماند  و سپس اجرای عملکرد async را از سر می گیرد و مقدار resolved شده را برمی گرداند.

unction resolveAfter2Seconds(x) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(x);
        }, 2000);
    });
}


async function add1(x) {
    const a = await resolveAfter2Seconds(20);
    const b = await resolveAfter2Seconds(30);
    return x + a + b;
}

add1(10).then(v => {
    console.log(v); // prints 60 after 4 seconds.
});


async function add2(x) {
    const p_a = resolveAfter2Seconds(20);
    const p_b = resolveAfter2Seconds(30);
    return x + await p_a + await p_b;
}

add2(10).then(v => {
    console.log(v); // prints 60 after 2 seconds.
});

 

 

 

نظرات :

در عرض چند دقیقه برای ایجاد حساب

کاربری خود اقدام کنید


اکنون حساب کاربری خود را ایجاد کنید!


ایجاد حساب کاربری

با ثبت نام در نیلوتک از آخرین بروز رسانی های آموزش ها و مقالات سایت مطلع شوید