debounce를 wrap한 debounceWrapper를 만들어봅시다.

노요셉·2020년 7월 24일
0

목적

저장버튼를 여러번 눌러도 마지막 버튼요청만 RESTAPI를 통해 저장요청을 보내고싶어요.

이러한 목적에 사용되는 개념이 '디바운싱'이란 것이 있는데요. 간단하게 마지막 이벤트만 동작하게끔 하는 것입니다.

제로초의 디바운스 코드를 쓰는데 이런 작업이 반복이 되서 재활용하기 위해서 debounce 틀을 따로 빼서
로직을 함수로 감싸서 매개변수로 전달하는 방향으로 구현했어요.

  timer: number;
  ...
  
  onKeyDown(e: Event) {
    e.preventDefault();

    if (this.timer) {
      window.clearTimeout(this.timer);
    }
    this.timer = window.setTimeout(() => {
      this.onSearch(); // <- debounce를 적용할 로직
    }, 200);
  }

debounce 분리

function debounce(func, ms) {
  return (timerObj: {timer: number}) => {
    if (timerObj.timer) {
      window.clearTimeout(timerObj.timer);
    }
    timerObj.timer = window.setTimeout(() => {
      func(); // <- 로직이 돌아갈 위치
    }, ms);
  };
}

...
   debounce(() => {this.updateProject(processedParam); }, 1000)(this.timerObj);

여기서 눈여겨볼 것 두 가지.
1. dobounce메서드에서 timer를 객체로 전달한 것
2. debounce에 func을 보낼때

  1. debounce 메서드의 매개변수로 this.timer로 객체가 아닌 값을 전달하면
    dobounce안에 if조건문에서 falsy값이 되기 때문에 timer를 계속 만들게 되요.
    callByReference를 원한거였는데, callByValue로 구현이 되었던 거죠.
    그래서 timer를 객체로 감싸서 전달하였습니다.

  2. func을 매개변수로 보낼때 보통 bind를 쓰잖아요. arrow function으로도 똑같이 동작하게 할 수 있어요.

   debounce(this.updateProject.bind(this, processedParam), 1000)(this.timerObj);

이렇게 arrow 함수로 감싸서 전달하는겁니다.

   debounce( () => { this.updateProject(processedParam); }, 1000)(this.timerObj);
profile
서로 아는 것들을 공유해요~

0개의 댓글