Перевод статьи «Debounce Explained – How to Make Your JavaScript Wait For Your User To Finish Typing» автора Juan Vega
Функция высшего порядка - это функция, которая принимает в качестве аргумента другую функцию, либо возвращает другую функцию в return. Наша debounce-функция делает и то, и другое.
Самый популярный способ использования debounce-функции - это добавление её в слушатель, прикрепленный к HTML-элементу. Чтобы лучше понять для чего это нужно и чем может быть полезным, давайте рассмотрим пример.
Допустим, у вас есть функция myFunc, которая вызывается каждый раз, когда вы что-то вводите в текстовое поле. После того, как все требования к проекту удовлетворены, вы решаете слегка изменить это поведение.
Вы хотите, чтобы функция выполнялась после того, как прошло хотя бы 2 секунды с момента ввода.
Вот здесь debounce-функция и выходит на сцену. Вместо того, чтобы передавать myFunc слушателю событий, вы должны передать в него debounce-функцию. А в debounce-функцию передать функцию myFunc и задержку в 2000 миллисекунд.
Теперь, каждый раз, когда вы жмёте клавишу, myFunc будет выполняться только если прошло 2 секунды с последнего момента вызова функции.
Как создать debounce-функцию?
Весь код займёт 7 строк. Оставшуюся часть статьи мы будем разбирать эти 7 строк, чтобы понять как это всё работает.
function debounce( callback, delay ) {
let timeout;
return function() {
clearTimeout( timeout );
timeout = setTimeout( callback, delay );
}
}
Итак, на первой строке мы объявили функцию debounce. Эта функция принимает два аргумента - callback и delay.
function debounce( callback, delay ) {
}
callback
- это любая функция, выполнение которой нужно ограничить.
delay
- время в миллисекундах, которое указывает задержку.
function debounce( callback, delay ) {
let timeout;
}
На второй строке мы объявляем переменную timeout, которая будет хранить timeoutID, возвращаемый при установке интервала через setTimeout.
function debounce( callback, delay ) {
let timeout;
return function() {
}
}
На третьей строке мы возвращаем анонимную функцию. Эта функция, через замыкание, позволит нам получить доступ к переменной timeout после того, как выполнение функции debounce закончится.
Замыкание в JS происходит каждый раз, когда функция сохраняет доступ к лексической области внешней функции, даже если внешняя функция уже выполнилась. Если хотите узнать больше, можете почитать главу 7 книги «Вы не знаете JS»
function debounce( callback, delay ) {
let timeout;
return function() {
clearTimeout( timeout );
}
}
На четвёртой строке мы вызываем clearTimeout. Это гарантирует нам, что при каждом вызове debounce будет сбрасывать timeout и отсчёт будет начинаться с нуля.
function debounce( callback, delay ) {
let timeout;
return function() {
clearTimeout( timeout );
timeout = setTimeout( callback, delay );
}
}
На пятой строке мы достигаем конца функции debounce.
Мы вызываем setTimeout, чтобы создать таймаут, с указанной в delay задержкой, который выполнит функцию callback, так же переданную аргументом. Вызов setTimeout вернёт нам timeoutID, который мы запишем в переменную timeout, чтобы мы могли сбросить таймаут и начать отсчёт с нуля, если функция debounce будет вызвана ещё раз.
Строки 6 и 7 содержат только закрывающие скобки, так что нет смысла их рассматривать.
Именно так работает debounce-функция изнутри. Теперь давайте добавим всё это к примеру из начала статьи. Мы создадим инпут и добавим слушатель с нашей debounce-функцией.
Пример из реального мира
Для начала, создадим инпут.
<label for="myInput">Type something in!</label>
<input id="myInput" type="text">
Теперь создадим функцию, которая будет что-то делать, когда мы будем вводить текст в наш инпут.
function helloWorld() {
console.log("Hello World!")
}
И наконец мы мы должны добавить к нашему инпуту слушатель на событие keyup.
const myInput = document.getElementById("myInput");
myInput.addEventListener(
"keyup",
debounce( helloWorld, 2000 )
);
Теперь, при вводе данных в поле, функция helloWorld будет выполняться только если с момента завершения ввода прошло 2 секунды.
Особое спасибо пользователю Reddit с ником stratoscope за помощь с поправками в изначальном коде в статье.
Debounce-функция - это простая, но довольно мощная штука, которая может оказать большое влияние на JS-приложение. Многие компании используют её, чтобы улучшить производительность своих приложений.
Если вы хотите узнать больше о JS, заходите на сайт автора juanmvega.com.
Поделиться