یاد بگیرید که چگونه از تکنیک debounce و throttling در جاوا اسکریپت برای بهینه سازی برنامه خود استفاده کنید.
بهینه سازی کد یکی از موثرترین راه ها برای بهبود عملکرد برنامه شماست. Debounce و throttling دو تکنیک ضروری بهینه سازی کد برای جاوا اسکریپت هستند. استفاده از هر دو تکنیک به بهبود تجربه کاربری اپلیکیشن شما کمک می کند و همچنین در هزینه های خود صرفه جویی می کنید.
رفتار پیش فرض دسترسی DOM
قبل از غواصی عمیق در debounce و throttling، باید بدانید که چرا هر دو تکنیک با استفاده از چند کد مثال مهم هستند.
یک فایل index.html ایجاد کنید و کد زیر را در آن قرار دهید:
<input type="text" />
<div>
<b>Default:</b>
<span id="default"></span>
</div>
<div>
<b>Debounce:</b>
<span id="debounce"></span>
</div>
<div>
<b>Throttle:</b>
<span id="throttle"></span>
</div>
<script src="script.js" />
اولین عنصر ورودی برای جمع آوری اطلاعات است. سپس سه div و یک عنصر span داخلی برای خروجی متن در حالت های پیش فرض، debounce و throttling وجود دارد. هدف این عناصر نشان دادن و مقایسه سه تکنیک با یکدیگر است.
فایل script.js را ایجاد کنید و با انتخاب تمام عناصر صفحه شروع کنید:
const input = document.querySelector('input')
const defaultText = document.getElementById('default')
const debounceText = document.getElementById('debounce')
const throttleText = document.getElementById('throttle')
برای بررسی عمیق روشهای دسترسی DOM مانند querySelector()، باید پیمایش DOM در جاوا اسکریپت را بدانید.
سپس، شنونده رویداد را به ورودی اضافه کنید. این فقط هر چیزی را که تایپ شده در فرم می گیرد و آن را به عنوان محتوای درونی اولین عنصر span ارسال می کند:
input.addEventListener("input", e=> {
defaultText.textContent = e.target.value
})
وقتی چیزی را در ورودی خود تایپ می کنید، متن همانطور که در تصویر زیر نشان داده شده است در صفحه نمایش داده می شود.
این روش پیشفرض چاپ مقادیر زمانی کار میکند که فقط به صورت محلی روی رایانه خود کار میکنید. این فرآیند بسیار سریع است و بدون توجه به اتصال شبکه شما، هیچ مشکلی در عملکرد ایجاد نخواهد کرد. این به این دلیل است که شما فقط همه چیز را به صورت محلی در صفحه خود ذخیره می کنید. این مشکل زمانی ایجاد می شود که شما داده ها را از یک سرور خارجی دریافت می کنید.
مشکل در برقراری تماس های چند منظوره
تصور کنید که ورودی یک کادر تکمیل خودکار است. وقتی چیزی را در کادر تایپ می کنید، به سرور می رود و مجموعه ای از اطلاعات را جستجو می کند. برای مثال، ممکن است از پایگاه داده پرس و جو کنید تا تمام حرکاتی را که عبارت ماتریس در آن وجود دارد، بازیابی کنید.
مشکل اینجاست: همانطور که هر کاراکتر را تایپ می کنید، کد یک درخواست جدید ارسال می کند زیرا هر بار که یک کاراکتر جدید تایپ می کنید رویداد ورودی فعال می شود.
بنابراین وقتی m را تایپ میکنید، برای همه فیلمهایی که با m شروع میشوند درخواست میشود. وقتی ma را انجام میدهید، درخواست دیگری ارسال میکند و فیلمها را که با ma شروع میشوند برمیگرداند. و غیره.
با تایپ کلمه matrix شش درخواست به سرور خود می دهیم. این نه تنها باعث ایجاد برخی از مشکلات رابط کاربری می شود، بلکه برای کسانی که از کد شما استفاده می کنند نیز سنگین است. این به این دلیل است که آنها باید شش درخواست شبکه ارائه دهند، که در صورت اتصال کند، سرعت برنامه را کاهش می دهد.
اینجاست که انحراف و فشار وارد می شود. هر دو تکنیک به شما کمک می کنند تا با درخواست های کمتر، منابع را حفظ کنید. به جای اینکه هر بار یک تابع را فراخوانی کند، آن تابع را فقط پس از یک تاخیر تنظیم شده فراخوانی می کند. این تأخیر بر اساس debouncing و throttling متفاوت خواهد بود (هر دو روش متفاوت عمل می کنند).
با استفاده از تکنیک Debounce
به جای فراخوانی یک تابع هر بار که یک کاراکتر را در یک فیلد ورودی تایپ میکنید، جهش با فراخوانی تابع و منتظر ماندن مقدار مشخصی از زمان (مثلاً یک ثانیه) کار میکند.
اگر چیزی در آن بازه زمانی تغییر نکند، تابع را فراخوانی می کند. اما اگر در طول این یک ثانیه، کاراکتر دیگری را تایپ کنید، متوجه تغییر می شود و تایمر را به زمان تاخیر مشخص شده (یک ثانیه) بازنشانی می کند.
در اصل، debounce برای یک دوره زمانی منتظر می ماند (توسط شما تنظیم شده است)، و اگر در این مدت چیزی تغییر نکرد، تابع را فراخوانی می کند. اما اگر تغییری رخ دهد، تایمر تنظیم مجدد می شود. تکنیک debounce را می توان با کمک برخی کدها بهتر درک کرد.
در زیر اولین شنونده رویداد، یک تابع به نام debounce ایجاد کنید. شما یک تابع پاسخ به تماس و همچنین تاخیر پیشفرض یک ثانیهای را به حالت rebounce ارسال میکنید.
function debounce(cb, delay = 1000) {
return (...args) => {
setTimeout(() => {
cb(...args)
}, delay)
}
}
اساساً، شما عملکرد را مجبور میکنید تا قبل از اجرای عملکرد پاسخ به تماس، یک ثانیه صبر کند. سپس تابع debounce را به updateDebounceText منتقل کنید. یک تابع callback به آن بدهید که یک متن را به عنوان آرگومان می گیرد و عنصر debounceText را با محتوای متن به روز می کند.
const updateDebounceText = debounce((text) => {
debounceText.textContent = text
})
فراخوانی یک تابع ناشناس است که روش خاصی برای نوشتن توابع در جاوا اسکریپت است. در نهایت، تابع updateDebounceText را در شنونده رویداد فراخوانی کنید تا به متن ورودی دسترسی پیدا کند و آن را در صفحه چاپ کند:
input.addEventListener("input", e=> {
defaultText.textContent = e.target.value
updateDebounceText(e.target.value)
})
فایل را ذخیره کنید و به مرورگر خود بروید. همانطور که در ورودی فرم تایپ می کنید، یک ثانیه تاخیر تا زمانی که متن در کنار Debounce ظاهر شود، متوجه خواهید شد.
این دقیقاً نحوه عملکرد تکنیک debounce نیست. شما اینجا فقط یک ثانیه کارها را به تاخیر می اندازید.
در عوض، میخواهید مطمئن شوید که همه آن فراخوانیهای تابع برای هر کاراکتر اجرا نمیشوند تا زمانی که همه چیز را تایپ کنید. این کار را با پاک کردن مهلت زمانی که تابع را فرا میخوانید انجام میدهید. در اینجا کد اصلاح شده برای آن آمده است:
function debounce(cb, delay = 1000) {
let timeout
return (...args) => {
clearTimeout(timeout)
timeout = setTimeout(() => {
cb(...args)
}, delay)
}
}
بنابراین هر بار که ورودی شما تغییر میکند، تابع updateDebounceText را فراخوانی میکنید که مهلت زمانی اصلی شما را پاک میکند و یک تایمر جدید یک ثانیهای را شروع میکند. در نتیجه، این تابع منتظر می ماند تا حداقل یک ثانیه تاخیر قبل از اجرای مجدد تماس وجود داشته باشد.
تصویر زیر صفحه را درست پس از تایپ آخرین کاراکتر در فرم ثبت می کند:
در این حالت، تمام ورودی ها را به یکباره به روز می کند. این به این دلیل است که هر بار که یک کاراکتر جدید تایپ می کنیم، تایمر تنظیم مجدد می شود، به همین دلیل است که کاراکتر به صفحه اضافه نمی شود.
Debouncing در این سناریوها که می خواهید اطلاعات را پس از یک تاخیر مشخص به جای هر به روز رسانی ارسال کنید، واقعا مفید است.
درک تکنیک دریچه گاز
دریچه گاز کمی با تکنیک دباونس متفاوت است. شبیه به debouncing، throttling تماس تابع شما را به تاخیر می اندازد. اما به جای اینکه منتظر بماند تا همه چیز تمام شود، به طور مداوم یک درخواست جدید با آخرین دسته از اطلاعات ارسال می کند.
بنابراین اگر تاخیر شما چهار ثانیه باشد، تابع دریچه گاز اولین دسته از کاراکترها را ارسال می کند، چهار ثانیه صبر کنید، سپس دسته جدیدی از کاراکترها را که در طول تاخیر تایپ کرده اید ارسال می کند.
تکنیک throttling زمانی مفید است که چندین مورد در حال تغییر هستند و شما میخواهید تازهترین بهروزرسانی را ارسال کنید. یک مثال مورد استفاده در هنگام تغییر اندازه یک پنجره یا پیمایش پنجره است. شما می خواهید مکان کاربر را بفهمید، اما نمی خواهید این روش را صد هزار بار فراخوانی کنید.
تکنیک دریچه گاز میزان توان مورد نیاز CPU را محدود می کند. عملکرد دریچه گاز اینجاست:
function throttle(cb, delay = 1000) {
let shouldWait = false
return(...args) => {
if (shouldWait) return
cb(...args)
shouldWait = true
setTimeout(() => {
shouldWait = false
}, delay)
}
}
اولین باری که throttle() را فرا میخوانید، فوراً تابع callback شما را فراخوانی میکند. و سپس هر بار دیگر که با آن تماس می گیرید، تا زمانی که تاخیر شما تمام نشود، هیچ کاری انجام نمی دهد. پس از اتمام آن، باید بایدWait را به false بازنشانی کنید (که کد را اجرا می کند و فرآیند را تکرار می کند).
تابع دریچه گاز را فراخوانی کنید و در تماس برگشتی عبور دهید:
const updateThrottleText = throttle((text) => {
throttleText.textContent = text
})
سپس، تابع را در کنترل کننده رویداد فراخوانی کنید:
input.addEventListener("input", e=> {
defaultText.textContent = e.target.value
updateDebounceText(e.target.value)
updateThrottleText(e.target.value)
})
حالا اگر ورودی را تایپ کنید، کاراکترها به صورت دستهای در فواصل یک ثانیهای بهروزرسانی میشوند. تصویر زیر صفحه را درست قبل از خروجی دسته دوم کاراکترها (ix) می گیرد.
اطلاعات بیشتر درباره بهینه سازی جاوا اسکریپت
یک کد بهینه برای افزایش سرعت و عملکرد کلی برنامه شما ضروری است. جاوا اسکریپت به طور طبیعی یک زبان سریع است، اما شیوه های کدنویسی ضعیف می تواند عملکرد برنامه شما را مختل کند. به همین دلیل است که اگر میخواهید یک توسعهدهنده برتر باشید، باید با تکنیکهای مختلف بهینهسازی کد جاوااسکریوت آشنا باشید.