51- آموزش جاوااسکریپت | Callback Function
در این آموزش با Callback Function آشنا میشوید و میبینید چگونه میتوان با آن ترتیب اجرای عملیاتهای همزمان و غیرهمزمان را کنترل کرد.
قبل از شروع ساخت کتابخانه اختصاصی AJAX، لازم است با یکی از مفاهیم مهم جاوااسکریپت یعنی Callback Function آشنا شویم.
دلیل این موضوع این است که در آن کتابخانه از callbackها استفاده خواهیم کرد، بنابراین بهتر است ابتدا مفهوم آن را با یک مثال ساده بررسی کنیم.
تا اینجا احتمالاً بارها بدون اینکه اسم آن را بدانید، از callback استفاده کردهاید.
به زبان ساده، callback تابعی است که بهعنوان آرگومان به تابع دیگری ارسال میشود و داخل همان تابع اجرا میشود.
برای مثال، زمانی که از forEach روی یک آرایه استفاده میکنیم و یک تابع به آن میدهیم، در واقع یک callback نوشتهایم.
const numbers = [1, 2, 3];
numbers.forEach(function (number) {
console.log(number);
});
در این مثال، تابعی که به forEach دادهایم یک callback است.
callback همزمان و غیرهمزمان
Callbackها میتوانند هم synchronous باشند و هم asynchronous.
- در callback همزمان، اجرای کد بهصورت ترتیبی انجام میشود.
- در callback غیرهمزمان، اجرای بقیه کدها متوقف نمیشود و نتیجه بعداً آماده میشود.
یکی از مثالهای رایج برای callback غیرهمزمان، setTimeout است.
setTimeout(function () {
console.log('Hello');
}, 2000);
در اینجا تابع داخل setTimeout بعد از 2 ثانیه اجرا میشود، اما اجرای برنامه در این مدت متوقف نمیشود.
چرا callback مهم است؟
برای درک بهتر، یک سناریوی ساده را شبیهسازی میکنیم.
فرض کنید میخواهیم یک پست جدید ایجاد کنیم و بعد از آن، همه پستها را دریافت کنیم.
اگر دریافت پستها زودتر از ثبت پست جدید انجام شود، پست تازه در خروجی نمایش داده نمیشود.
این اتفاق در کار با سرور، دیتابیس یا API کاملاً طبیعی است، چون پاسخها همیشه با تأخیر میرسند.
برای شبیهسازی این وضعیت، از setTimeout استفاده میکنیم.
نمونه اول: اجرای ناهمزمان بدون callback
در این مثال، یک آرایه را بهعنوان دادههای سرور در نظر میگیریم.
let posts = [
{ title: 'Post One', body: 'This is post one' },
{ title: 'Post Two', body: 'This is post two' }
];
function createPost(post) {
setTimeout(function () {
posts.push(post);
}, 2000);
}
function getPosts() {
setTimeout(function () {
let output = '';
posts.forEach(function (post) {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
createPost({ title: 'Post Three', body: 'This is post three' });
getPosts();
در این حالت، getPosts() بعد از 1 ثانیه اجرا میشود، اما createPost() بعد از 2 ثانیه پست جدید را اضافه میکند.
به همین دلیل، هنگام نمایش پستها، Post Three هنوز به آرایه اضافه نشده است.
نتیجه مشکل
در خروجی فقط دو پست اول نمایش داده میشوند، چون تابع دریافت پستها زودتر از تابع ایجاد پست اجرا شده است.
حل مشکل با callback
برای حل این مشکل، میتوانیم داخل تابع createPost یک callback بگیریم و بعد از افزودن پست جدید، آن callback را اجرا کنیم.
let posts = [
{ title: 'Post One', body: 'This is post one' },
{ title: 'Post Two', body: 'This is post two' }
];
function createPost(post, callback) {
setTimeout(function () {
posts.push(post);
callback();
}, 2000);
}
function getPosts() {
setTimeout(function () {
let output = '';
posts.forEach(function (post) {
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;
}, 1000);
}
createPost(
{ title: 'Post Three', body: 'This is post three' },
getPosts
);
در این نسخه:
- ابتدا
createPostاجرا میشود - بعد از اضافه شدن پست جدید،
callbackصدا زده میشود - سپس
getPostsاجرا میشود - در نتیجه،
Post Threeهم در خروجی دیده میشود
جمعبندی
Callback Function یکی از پایهایترین مفاهیم جاوااسکریپت است که در کار با توابع همزمان و غیرهمزمان نقش مهمی دارد.
در این آموزش دیدیم که:
- callback تابعی است که به تابع دیگر داده میشود
forEachوsetTimeoutنمونههای رایج استفاده از callback هستند- callback میتواند همزمان یا غیرهمزمان باشد
- برای کنترل ترتیب اجرای عملیاتهای وابسته، callback بسیار کاربردی است
در آموزش بعدی، از همین مفهوم برای ساخت کتابخانه اختصاصی AJAX استفاده میکنیم.