scroll, resize, input, mousemove 등 같은 이벤트를 짧은 시간에 연속적으로 발생하는 이벤트들이 있는데 이러한 이벤트들은 성능에 문제를 줄 수 있다.
디바운스와 쓰로틀은 짧은 시간에 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법이다.
// 디바운스 예시
<script>
const $input = document.querySelector("input");
const $text = document.querySelector(".text");
const debounce = (callback, delay) => {
let timeId;
// debounce 함수는 timeId를 기억하는 클로저를 반환
return event => {
// delay가 경과하기 이전에 이벤트가 발생하면 이전 타이머를 취소 -> 새로운 타이머 재설정
// delay보다 짧은 간격으로 이벤트가 발생하면 callback은 호출 안됨
if(timeId) clearTimeout(timeId);
timeId = setTimeout(callback, delay, event);
};
};
// debounce 함수가 반환하는 클로저가 이벤트 핸들러 등록
// 300ms보다 짧은 간격으로 이벤트 발생하면 debounce 함수의 콜백 호출 안함
// 300ms 동안 input 이벤트가 발생하지 않으면 debounce 함수 호출!
$input.oninput = debounce(e => {
$text.textContent = e.target.value;
}, 300)
</script>
주로 resize이벤트, input 요소에 입력된 값으로 ajax 요청하는 자동완성 기능, 버튼 중복클릭 방지 처리 등에 사용된다.
Underscore의 debounce 함수나 Lodash의 debounce 함수를 권장
// 스로틀 예시
<script>
const $container = document.querySelector(".container");
const $text = document.querySelector(".text");
const throttle = (callback, delay) => {
let timeId;
// throttle 함수는 timeId를 기억하는 클로저를 반환
return event => {
// delay가 경과하기 이전에 이벤트가 발생하면 아무 것도 하지 않음
// delay 간격으로 callback 호출
if(timeId) return;
timeId = setTimeout(() => {
callback(event);
timeId = null;
}, delay, event);
};
};
$container.addEventListener("scroll", throttle(() => {
$text.textContent = ++ throttle;
}, 100));
</script>
주로 scroll 이벤트 처리나 무한 스크롤 구현에 쓰인다.
Underscore의 throttle 함수나 Lodash의 throttle 함수를 권장