requestAnimationFrame, debouncing, throttle

Ahyeon, Jung·2023년 10월 11일
0

requestAnimationFrame

사람들은 1초당 60프레임 이상 체감할 수 없기 때문에, 깔끔한 애니메이션에 대한 기준은 1초당 60FPS
즉, 1프레임은 16.6 ms초 소요

setTimeout, setInterval로 대체 가능?

setTimeout(callback, 16.6)으로 일단은 구현가능함
but
setTimeout, setInterval은 단순히 해당 시점이 되면 내부에 있는 콜백을 실행하는 함수 => '시간중심'

내부에 있는 콜백이 복잡한 연산이 필요하거나, 혹은 reflow -> repaint 단계를 반복하는 형태라면 정해진 시간에 내부 동작이 수행될 수는 있어도 움직임이 끊겨보이는 프레임 드랍 현상이 발생가능함

but requsetAnimationFrame은 시간이 아닌, Frame을 깔끔하게 그릴 수 있느냐로 판단함
16.6ms에 1프레임을 온전하게 그릴 수 있도록 동작을 수행 => 애니메이션 최적화 가능

동작원리의 차이

마이크로 태스크 큐, 애니메이션 태스크 큐, 매크로 태스크 큐 순서로 우선순위를 가져 이벤트 루프가 동작

Promise는 마이크로 태스크 큐
requsetAnimationFrame은 애니메이션 프레임 큐
setTimeout, setInterval은 매크로 태스크 큐

debouncing

  1. 최초 호출이 일어나면, 변수에 setTimeout을 할당
  2. 만약 호출이 수행되기 전에 호출이 일어나면, 기존에 할당되어 있던 timeout을 해제하고 새로운 timeout의 id를 할당

=> 5000초가 지나기 전에 호출이 일어나면 5000초를 다시 기다려서 콜백을 실행함
=> 일정 시간 내의 이벤트를 무시하고 마지막 호출을 실행함

let debounceTimer

function debounce(){
 if (debounceTimer) clearTimeout(timer); 

 // 콜백함수가 있으면 지우고 다시 콜백함수를 매크로 태스크 큐에 설정

 debounceTimer = setTimeout(()=>{
  doSomething()
 }, 500)
}

throttle

호출이 일어난 이후, 일정 시간 내에 재호출이 일어나지 않게함

=> 일정 시간 내의 후속 이벤트를 무시하고 처음만 실행함

let throttleTimer;

function throttle(){
 if (!throttleTimer){ // timer 저장된게 없으면 500초동안 if문에 들어오지못해 실행이 안됨
  throttleTimer = setTimeout(()=>{
   doSomething();
   throttleTimer = null;
  },500)
 }
}

Reference

https://developer.mozilla.org/ko/docs/Web/API/window/requestAnimationFrame
https://kdt-gitlab.elice.io/ai_track/class_08/ai-project/team02/team2/-/issues/16

profile
https://a-honey.tistory.com/

0개의 댓글