پیاده‌سازی تابع Debounce ‌در زبان JavaScript


۲۴ آبان ۱۳۹۹
پیاده‌سازی تابع debounce در زبان javascript

اگر بخواهیم توابع debounce را شرح دهیم می‌توان گفت که آنها در دسته توابع higher-order قرار می‌گیرند و با استفاده از آنها می‌توانیم سرعت فراخوانی تابع دیگری را محدود کنیم، مثلا منتظر بمانیم تا تایپ کردن کاربر تمام شود و سپس نتایج را به او نشان دهیم.

توابع higher-order، تابعی را به عنوان ورودی دریافت یا تابعی را return می‌کنند، اما تابع debounce هر دو کار را انجام می‌دهد. یکی از معمول‌ترین استفاده‌ها از تابع debounce برای ارسال argument به event listener یک المنت HTML است. برای درک بهتر فایده و ساختار آن، به مثال زیر دقت داشته باشید.

جستجوی کلمه‌ی canada با استفاده از debounce

فرض کنید که شما تابعی با نام myFunc را در هر بار که چیزی در قسمت input تایپ می‌شود، فراخوانی می‌کنید اما بعد از مدتی تصمیم می‌گیرید که تجربه کاربری برنامه خود را تغییر دهید. مثلا می‌خواهید که تابع myFunc، دو ثانیه پس از تایپ آخرین کلمه اجرا شود. این همان جایی است که شما می‌توانید از تابع debounce استفاده کنید. بنابراین می‌بایست به‌جای تابع myFunc از تابع debounce خود در event listener استفاده کرده و سپس تابع myFunc را به عنوان یک ورودی به تابع debounce می‌دهید.

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

نحوه پیاده‌سازی تابع debounce

کدهای زیر همان ۷ خط کدی هستند که باید در پیاده‌سازی تابع debounce درک کنید.

function debounce( callback, delay ) {
    let timeout;
    return function() {
        clearTimeout( timeout );
        timeout = setTimeout( callback, delay );
    }
}

با خط اول شروع می‌کنیم، یک تابع با نام debounce ایجاد کرده‌ایم که دو ورودی با نام‌های callback و delay دریافت می‌کند.

function debounce( callback, delay ) {

}

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

function debounce( callback, delay ) {
    let timeout;
}

در خط دوم، یک متغیر با نام timeout تعریف می‌کنیم. این متغیر جدید مقدار timeoutID را که از فراخوانی setTimeout به‌دست می‌آید، در خود نگه می‌دارد.

function debounce( callback, delay ) {
    let timeout;
    return function() {
    }
}

در خط سوم، زیر متغیر timeout یک تابع anonymous را return می‌کنیم تا پس از اجرای تابع debounce بتوانیم به مقدار آن دسترسی داشته باشیم.

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

function debounce( callback, delay ) {
    let timeout;
    return function() {
        clearTimeout( timeout );
    }
}

در خط چهارم از متد clearTimeout که از mixin WindowOrWorkerGlobalScope نشعت گرفته، استفاده می‌کنیم. با این کار اطمینان حاصل می‌شود که هر بار تابع debounce اجرا می‌شود، مقدار timeout مجددا تنظیم شده و شمارش شروع می‌شود.

شما با استفاده ازWindowOrWorkerGlobalScope در زبان JavaScript می‌توانید به متدهای شناخته شده‌ای مانند setTimeout، clearTimeout، setInterval، clearInterval و fetch دسترسی داشته باشید.

function debounce( callback, delay ) {
    let timeout;
    return function() {
        clearTimeout( timeout );
        timeout = setTimeout( callback, delay );
    }
}

در خط پنجم به پایان پیاده‌سازی تابع debounce می‌رسیم. در این خط کد، چندین کار انجام می‌شود. اولین کار، اختصاص مقدار timeoutID با فراخوانی تابع setTimeout به متغیر timeout است که در خط دوم تعریف کرده بودیم. این کار به ما امکان می‌دهد که با فراخوانی تابع setTimeout یک reference به متغیر timeout بسازیم، بنابراین می‌توانیم مقدار timeout را در هر بار فراخوانی تابع debounce، مجددا تنظیم کنیم.

کار بعدی فراخوانی تابع setTimeout است و با استفاده از این تابع می‌توانید یک تاخیر در اجرای تابع callback ایجاد کنید.

از آنجا که ما از timeout استفاده می‌کنیم، تابع callback زمانی اجرا می‌شود که مقدار این متغیر به صفر برسد. به این صورت با هر بار فراخوانی تابع debounce، مقدار متغیر timeout مجددا به مقدار delay بازنشانی می‌شود و بدین صورت می‌توانیم اجرای تابع myFunc را محدود کنیم.

خط‌های ۶ و ۷ شامل براکت‌ها هستند که مطمئنا نیازی به توضیح ندارند.

تا اینجا متوجه شدید که عملکرد تابع debounce به چه شکل است، در ادامه با استفاده از توضیحات قبل، یک مثال واقعی از کارکرد این تابع را بررسی خواهیم کرد.

استفاده از تابع debounce در یک پروژه واقعی

ابتدا با استفاده از کدهای HTML، یک input ایجاد می‌کنیم:

<label for="myInput">Type something in!</label>
<input id="myInput" type="text">

در مرحله بعد، تابعی که می‌خواهیم هر زمان متنی در input وارد شد، اجرا شود را تعریف می‌کنیم:

function helloWorld() {
    console.log("Hello World!")
}

سپس با استفاده از زبان JavaScript، به المنت input خود یک keyup event listener اضافه می‌کنیم:

const myInput = document.getElementById("myInput");

myInput.addEventListener(
    "keyup",
    debounce( helloWorld, 2000 )
);

در نهایت با استفاده از کدهای بالا، اگر از آخرین کلمه‌ای که در input تایپ کرده‌ایم حداقل ۲ ثانیه گذشته باشد، تابع helloWorld اجرا می‌شود.

جمع‌بندی پایانی

توابع debounce بسیار ساده و در عین حال قدرتمند هستند، همچنین می‌توانند تاثیر قابل توجهی در اکثر برنامه‌های JavaScript داشته باشند. با اینکه مثال ما بسیار ساده بود اما سازمان‌های بزرگ از توابع debounce برای افزایش عملکرد برنامه‌هایشان استفاده می‌کنند.

منبع: https://www.freecodecamp.org/news/debounce-explained-how-to-make-your-javascript-wait-for-your-user-to-finish-typing-2

برچسب‌ها:

خدمات رایگان لیارا

۲.۵ گیگابایت فضای ذخیره‌سازی ابری رایگان

۲.۵ گیگابایت Object Storage سازگار با پروتکل S3 با دیسک‌های SSD به‌صورت رایگان دریافت کنید.

هاست رایگان برای دیتابیس‌

دیتابیس‌های MariaDB، PostgreSQL و Redis را فقط با یک کلیک و به‌صورت رایگان تهیه کنید.

سرویس DNS رایگان

به سادگی دامنه‌تان را اضافه کنید و به صورت رایگان رکورد‌های آن را مدیریت کنید.

۱۰۰ هزار تومان اعتبار اولیه

بعد از ثبت نام در لیارا مبلغ ۱۰۰ هزار تومان اعتبار هدیه دریافت می‌کنید که با توجه به ساعتی بودن هزینه سرویس‌ها، می‌توانید تمامی خدمات پولی را برای چندین هفته رایگان استفاده کنید.

ارسال ۱۰۰ ایمیل تراکنشی رایگان در هر ماه

در سرویس ایمیل لیارا شما می‌توانید تا ۱۰۰ ایمیل رایگان در هر ماه ارسال کنید و فقط برای بیش از آن هزینه پرداخت کنید. (به‌همراه دسترسی SMTP)

هاست رایگان برای انواع وبسایت

تفاوتی ندارد برای وبسایت خود از Node استفاده می‌کنید یا Laravel و Django، در لیارا می‌توانید به صورت کاملا رایگان آن را میزبانی کنید.

توسعه‌دهندگان درباره‌ی ما چه می‌گویند

تجربه کار باliara_cloud@امروز خیلی خوب بود. یکی از سرویس هام رو منتقل کردم روش و راضیم. انقد سریع و جذاب کارم راه افتادم اصن باورم نمیشد! برعکس سرویس های PaaS دیگه با اون همه پیچیدگیشون. دمتون گرم
...

MohammadReza
liara testimonial
keikaavousi

بعد از بسته شدن @fandoghpaas و ناراحتی همه‌مون از اینکه یه سرویس خوب و صادق نمی‌تونه از پس هزینه‌ها بر بیاد، سرویسم رو منتقل کردم به پاس لیارا (https://liara.ir @liara_cloud) . تجربه راحت و خوب. تفاوت‌هایی داشت که کمی کار می‌خواست ولی تا الان کاملا راضی.

jadi
liara testimonial
jadi

یه خسته نباشید باید به تصمیمliara_cloud@بگم،
بعد از چندین روز سرکله زدن با سرویس های مشابه بالاخره تصمیم گرفتم لیارا رو امتحان کنم و باور نمیشه ۱۰ دقیقه بیشتر وقت نبرد،
دمتون گرم.

Arch
liara testimonial
EbadiDev

واسه سرویس PaaS با اختلاف لیارا بهترین رابط کاربری داره و یکی از مزیت‌های سرویس دیتابیس‌شون اینه که خودشون به صورت دوره‌ای بکآپ میگیرن.
...

Ali Najafi
liara testimonial
me_ali_najafi

یکی از کارهای خوبی که جدیداً میکنم اینه که یه دیتابیس روی لیارا میسازم و به پروژه وصل میکنم اینطوری هم خونه و هم محل کار دیتابیس بروز رو دارم و راحت میتونم ادامه بدم کار روliara_cloud@

Navid
liara testimonial
1navid

عاشقliara_cloud@شدم درسته در حد AWS نیست ولی خب تجربه خوبی واسه پروژه های داخل ایران ارائه میده، میتونم رو CD هم اجراش کنم

Amir H Shekari
liara testimonial
vanenshi

همراه شما هستیم

در خصوص سفارش یا استفاده از سرویس‌ها سوالی دارید؟
تلفن واحد فروش:
۰۲۵-۳۳۵۵۷۶۱۹ (روزهای کاری ۹ الی ۱۷)
تلفن واحد فروش: ۳۳۵۵۷۶۱۹-۰۲۵ (روزهای کاری ۹ الی ۱۷)