Debounce & Throttle

zmin·2022년 8월 4일
0

둘 다 성능 향샹을 위한 것으로 연속되는 이벤트가 발생할 때 필요없이 지나치게 많은 실행이 일어나지 않도록 하는 방식이다.

두 방식이 비슷하지만 다른 부분이 있고 내가 이해한 건 아래와 같다.

Throttle: 입력이 들어오는 시간 기준

대기 상태시에 이벤트가 발생하면 타이머가 작동하고 끝날 때까지 이벤트를 제어함

일반적으로 이벤트 사이 시간이 일정하다는 것이 특징

  • leading :
    대기상태일 때 어떤 이벤트가 발생하면 일단 실행하고 timer를 동작시킴
    → 이 타이머가 끝날 때까지 들어오는 모든 이벤트들 무시
    → 타이머가 끝나면 다시 대기 상태
     let timer = 0;
     
     const throttleLeading = (func: () => void, delay: number) : void => {
     		// 현재 타이머가 있는지 검사, timer는 양수인 정수를 뱉어냄
         if(timer !== 0)
             return;
     
         func();
         timer = setTimeout(()=>{
             clearTimeout(timer);
             timer = 0;
         }, delay);
     };
  • trailing :
    대기상태일 때 어떤 이벤트가 발생하면 timer를 동작시킴
    → 해당 타이머가 진행하는 동안 발생한 이벤트 중 가장 마지막 이벤트만 해당 타이머가 끝날 때 실행시킴
    → 다시 대기
     let timer = 0;
     let lastFunc : Function;
     
     const throttleTrailing = (func: () => void, delay: number): void => {
         lastFunc = func;
         console.log(Date.now());
         if(timer === 0)
             timer = setTimeout(() => {
                 lastFunc();
                 clearTimeout(timer);
                 timer = 0;
             }, delay);
     };
  • leading & trailing : 둘 다 실행
    let timer = 0;
    let lastFunc : Function;
    
    const throttleLeadingAndTrailing = (func: () => void, delay: number): void => {
        lastFunc = func;
        if(timer === 0) {
            func();
            timer = setTimeout(()=>{
                lastFunc();
                clearTimeout(timer);
                timer = 0;
            }, delay);
        }
    };

Debounce: 입력이 안 들어오는 시간 기준

일정시간동안 이벤트가 발생하지 않으면 실행

이벤트가 발생할 때마다 타이머가 초기화, 이 타이머가 끝날 때까지 이벤트가 들어오지 않아야 타이머가 정상적으로 종료될 수 있음 → 이벤트가 타이머를 제어

  • leading : 말 그대로 이끔 → 첫 이벤트 실행 후 대기(이벤트 발생 시점과 실행시점이 동일)
    let timer = 0;
    
    const debounceLeading = (func: () => void, delay: number): void => {
        if(timer === 0)
            func();
    
        clearTimeout(timer);
        timer = setTimeout(() => {
            clearTimeout(timer);
            timer = 0;
        }, delay);
    };
  • trailing : 말 그대로 뒤 따라감 → 대기 후 마지막 이벤트 실행(이벤트 발생 시점보다 실행시점이 delay 만큼 늦음)
    let timer: number;
    
    const debounceTrailing = (func: () => void, delay: number): void => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            const executionTime = Date.now();
            clearTimeout(timer);
            func();
        }, delay); 
    };
  • leading & trailing : 둘 다 실행
    let timer = 0;
    
    const debounceLeadingAndTrailing = (func: () => void, delay: number): void => {
          if(timer === 0)
              func();
    
          clearTimeout(timer);
          timer = setTimeout(() => {
              func();
              clearTimeout(timer);
              timer = 0
          }, delay);
    };

클래스로 구분한 전체 코드

 <!DOCTYPE html>
 <html lang="en">
 <head>
 	<meta charset="UTF-8">
 	<title>Title</title>
 </head>
 <body>
 	<button id="add-button">add</button>
 	<div>값: <b id="value">0</b></div>
 	<script src="index.js" />
 </body>
 </html>

위는 테스트 페이지 html

 const button = document.getElementById('add-button');
 const value = document.getElementById('value');
 
 const plus = () => {
     value.innerText = String(Number(value.innerText) + 1);
 };
 
 // 실행부분
 button.addEventListener('click', () => Debounce.leadingAndTrailing(plus, 2000));
 
 class Debounce {
     static timer: number = 0;
 
     static trailing(func: () => void, delay: number) : void {
         clearTimeout(this.timer);
         this.timer = setTimeout(() => {
             const executionTime = Date.now();
             clearTimeout(this.timer);
             func();
         }, delay);
     }
     static leading(func: () => void, delay: number) : void {
         if(this.timer === 0)
             func();
 
         clearTimeout(this.timer);
         this.timer = setTimeout(() => {
             clearTimeout(this.timer);
             this.timer = 0;
         }, delay);
     }
 
     static leadingAndTrailing(func: () => void, delay: number) : void{
         if(this.timer === 0)
             func();
 
         clearTimeout(this.timer);
         this.timer = setTimeout(() => {
             func();
             clearTimeout(this.timer);
             this.timer = 0
         }, delay);
     }
 }
 
 class Throttle {
     static timer: number = 0;
     static lastFunc: Function;
 
     static trailing (func: () => void, delay: number) : void {
         this.lastFunc = func;
         if (this.timer === 0)
             this.timer = setTimeout(() => {
                 this.lastFunc();
                 clearTimeout(this.timer);
                 this.timer = 0;
             }, delay);
     }
 
     static leading (func: () => void, delay: number) : void {
         if(this.timer !== 0)
             return;
 
         func();
         this.timer = setTimeout(()=>{
             clearTimeout(this.timer);
             this.timer = 0;
         }, delay);
     }
 
     static leadingAndTrailing(func: () => void, delay: number) : void {
         this.lastFunc = func;
         if(this.timer === 0) {
             func();
             this.timer = setTimeout(()=>{
                 this.lastFunc();
                 clearTimeout(this.timer);
                 this.timer = 0;
             }, delay);
         }
     }
 }
profile
308 Permanent Redirect

0개의 댓글