본문 바로가기

dev/JavaScript

debounce와 throttle

개인 프로젝트 중 무의미한 스크롤 이벤트를 줄여야 했습니다.

그 과정에서 debounce, throttle 개념에 대해 알게 되어 정리 차 글로 남깁니다.

 

debounce

맨 마지막으로 호출된 함수만 실행시킵니다. 아래와 같은 형태로 작동합니다.

중간에 함수가 다시 호출되면 타이머를 초기화 하고 delay 만큼 기다린 후 실행합니다.

따라서 최종적으로는 마지막 fn()이 호출된 시점 + delay 후에 함수가 실행됩니다.

function debounce(fn, delay) {
  let timer = null; // timer 은닉을 위해 클로저를 사용
  return function () {
    // 클로저 함수 안에서 this 와 arguments 변수로 디바운싱 함수의 스코프와 변수에 접근
    const context = this;
    const args = arguments;
    clearTimeout(timer); // delay 함수가 다시 호출되면 타이머를 리셋한다.
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay); // delay 동안 호출이 없으면 fn을 실행한다.
  };
}

throttle

한번 함수가 호출되면 일정 시간동안은 다시 호출하지 않습니다.

게임에서 스킬스면 쿨타임 도는거랑 비슷한 느낌이네요...

function throttle(fn, threshhold = 250) {
  let lastCallTime, deferTimer;
  return function () {
    const context = this;
    const args = arguments;
    const now = Date.now();

    if (lastCallTime && now < lastCallTime + threshhold) {
      // 호출된 적이 있다면, 마지막 호출 시점부터 threshhold 만큼 시간이 지났을 때만 재호출
      clearTimeout(deferTimer);
      deferTimer = setTimeout(function () {
        lastCallTime = now;
        fn.apply(context, args);
      }, threshhold);
    } else {
      // 한번도 호출된 적 없으면 즉시 호출
      lastCallTime = now;
      fn.apply(context, args);
    }
  };
}