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


جاوا اسکریپت با قابلیت های closure ، first class functions و دیگر قابلیت هاش یک زبان برنامه نویسی قدرتمند شناخته میشه از طرفی جاوا اسکریپت اغلب برای برنامه نویسی Asynchronous استفاده میشه خوب چطور اینکارو انجام میده با قابلیتی به نام Callback میخوام تو این مقاله با یک مثال توضیح بدم که چطور میتونیم یک callback بنویسیم .

میخوام در چند مقاله نگاهی به سیر تحول برنامه نویسی ناهمزمان را در JavaScript از callback تا async await داشته باشیم تا درک دقیقتری از این موضوع پیدا کنیم و این درک قطعا کمکی زیادی در برنامه نویسی Node.js و جاوا اسکریپت می کنه. با من همراه باشید ...



برنامه نویسی Asynchronous

این نوع برنامه نویسی یا برنامه نویسی غیر همزمان، زمانی استفاده میشه که نیازه به عملیات i/o داشته باشیم. مثه کار با database، دانلود عکس ، نوشتن روی دیسک و .... ، اینا همشون عملیات i/o محسوب میشن. بعبارتی همشون یکم زمان نیاز دارن و ممکنه جوابش همون لحظه آماده نباشه. و از طرفی نمیدونیم چقدر زمان لازمه که جوابش حاضر بشه ممکنه یه ثانیه ممکن 5 ثانیه یا یک دقیقه ... خوب بنظرتون چطور این موضوع رو باید سمت خودمون مدیریت کنیم

بیایین با مثال بیشتر بررسی کنیم فرض کنید که عملیاتی داریم که دو ثانیه طول میکشه اجرا بشه از تابع setTimeout کمک میگیریم تا این تابع رو بنویسیم این تابع قراره بره و از دیتابیس عنوان یک پست رو برامون بیاره تا به کاربر نشون بدیم.

const getBlogPost = () => {
    setTimeout(() => {
        return {
            title: 'JavaScript Callbacks'
        }
    }, 2000);
};
 
const blogpost = getBlogPost();
console.log(blogpost.title);

قبل اینکه پایین تر برین بنظرتون چه اتفاقی میفته خروجی چی میشه ؟؟



خوب این خروجی تکه کد بالاس :

express-rest $node index.js
C:nodeexpress-restindex.js:21
console.log(blogpost.title);
                     ^

TypeError: Cannot read property 'title' of undefined
    at Object. (C:nodeexpress-restindex.js:21:22)
    at Module._compile (module.js:643:30)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)
    at Function.Module.runMain (module.js:684:10)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:608:3


خوب خروجی داره میگه نمیتونه title رو بخونه در واقع میگه اون undefined هست؟ علتش چیه ؟؟ یه مفهموم دیگه رو در اینجا لازمه بررسی کنیم، جاوا اسکریپت برای عملیات غیرهمزمان صبر نمیکنه تا کامل شن و جلو میره و بقیه کد ها رو به ترتیب از بالا به پایین اجرا میکنه . در واقع خط کد هایی رو اجرا میکنه که موجب توقف برنامه نمیشن. بعبارتی جاوا اسکریپ یک زبان no blocking هست. (بر خلاف زبانی های مثه java یا .net)

اینجا تو این مثال تابع getBlogPost() فورا اجرا میشه و 2 ثانیه منتظرش نمیمونه و مقدار blogpost رو میزاره undefined و به همین خاطر خروجی با خطا مواجع میشه.

خوب چطور اینو مدیریت کنیم ؟ این دلیلی هست که از callback باید استفاده کنیم.




کاربرد Callbackها در جاوا اسکریپت؟

توابع Callback در واقع توابعی هستند که می تونن بعنوان پارامتر یه تابع دیگه پاس داده بشن. معمولا معروف به high-order functions هم شناخته می شن که در واقع داخل اون تابعی که فراخوانی شده call میشن. معمولا هم زمانی استفاده میشن که نیازه به عملیات i/o داشته باشید.

حالا سعی میکنیم مثال بالا و مشکلی که بالا ایجاد شد رو با callback حل کنیم. به نحوه نوشتن تابع دقت کنید.

const getBlogPost = (callbackfunc) => {
    setTimeout(() => {
        callbackfunc({
            title: 'JavaScript Callbacks'
        });
    }, 2000);
};
 
getBlogPost((blogpost) => {    
     console.log(blogpost.title);
})

خروجی :


خوب خروجی همون چیزی که انتظار داشتیم بعد از 2 ثانیه title نمایش داده میشه. اگر به نحوی تعریف تابع نگاه کنید میبیند که چاپ title بعنوان یه تابع تعریف شده که بعنوان پارامتر یا همون callback به تابع getBlogPost ارسال میشه، بنابراین به محض اینکه 2 ثانیه تموم شد این تابع call میشه . به همین سادگی، به همین ...


این مقاله ادامه داره و در بخش بعدی میخوام سراغ اینکه چرا به promise نیاز داریم بپردازم خوشحال میشم با نظرتون در ادامه همراهیم کنید.


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

سپاس

حمید شجاع