JS - 디바운스와 스로틀

Jong-uk·2023년 11월 30일
0

JS

목록 보기
3/4

scroll, resize, input, mousemove 등 같은 이벤트를 짧은 시간에 연속적으로 발생하는 이벤트들이 있는데 이러한 이벤트들은 성능에 문제를 줄 수 있다.
디바운스쓰로틀은 짧은 시간에 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법이다.

디바운스

  • 짧은 시간 발생하는 이벤트를 그룹화해서 마지막에 한번만 이벤트 핸들러가 호출되도록 하는 기법
  • EX) input 이벤트가 짧은 시간 연속으로 발생하는 경우에 사용
// 디바운스 예시
<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 함수를 권장

profile
안녕하세요! 만나서 반갑습니다.

0개의 댓글