[modern JS Deep Dive] - 41장 . 타이머

유선향·2025년 1월 18일
0

<modern_JS_Deep_Dive>

목록 보기
36/44

호출 스케쥴링

본래 함수를 명시적으로 호출하면 함수가 즉시 실행되지만, 호출 스케쥴링으로 함수 호출을 예약함.

  • 자바스크립트 엔진은 싱글 스레드 ⇒ 태스크를 동시에 실행할수 없고, 타이머 함수는 비동기 처리 방식으로 동작한다.
  • 즉, setTimeout()은 함수 스택의 다른 함수 호출을 막지 않음

setTimeout

setTimeout(function () {
  console.log("Hello World!");
}, 500);

//this 문제를 방지하기위해 화살표로 작성 
setTimeout(() => {
 console.log("hello world" ;
}, 2000); 

중첩 타임 아웃

HTML 표준에 명시된 것과 같이, 브라우저는 setTimeout 호출이 5번 이상 중첩된 경우 4ms의 최소 지연 시간을 강제함.

setTimeout은 생성된 타이머를 식별할 수 있는 고유한 타이머 id를 반환( 숫자 or 객체)

해당 id를 clearTimeout 함수의 인수로 전달하여 타이머를 취소할 수 있다

clearTimeout(timeoutID)

setInterval( )

  • setInterval 는 생성된 타이머를 식별할 수 있는 고유한 타이머 아이디를 반환 (숫자 or 객체)
  • setInterval가 반환한 타이머 id 를 clearInterval() 함수의 인수로 전달하여 타이머를 취소한다.

디바운스와 스로틀


scroll, resize, input, mousemove 같이 자주 일어나는 이벤트에 바인딩한 이벤트 핸들러에는 디바운스와 스로틀을 이용

위의 이벤트를 그룹화 해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법 이다.

디바운스

일정 시간이 경과한 이후에 이벤트 핸들러가 한번만 호출되도록 한다.

디바운스는 이벤트를 그룹화 해서 마지막에 한번만 이벤트 핸들러가 호출 되도록 함.

전달한 시간보다 짧은 간격으로 이벤트가 발생하면 이전 타이머를 취소하고 새로운 타이머를 재 설정 한다. 따라서 딜레이 보다 짧은 간격으로 이벤트가 연속해서 발생하면 디바운스 함수의 첫번째 인수로 전달한 콜백 함수는 호출 되지않다가 딜레이 동안 이벤트가 더이상 발생하지 않으면 한번만 호출 된다.

스로틀

일정 시간 간격으로 이벤트 핸들러가 최대 한번만 호출되도록 한다.

즉 짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화 해서 일정 시간 단위로 핸들러가 호출되도록 호출 주기를 만든다.

두번째 인수로 전달한 시간이 경과하기 이전에 이벤트가 발생하면 아무것도 하지 않다가 딜레이 시간이 경과했을때 이벤트가 발생하면 콜백 함수를 호출하고 새로운 타이머를 재 설정한다.

scrollEvent, 무한 스크롤 등에 유용하게 사용된다.


requestAnimationFrame

  • 브라우저의 화면 리프레시 속도(FPS) 에 맞춰 함수를 실행하는 API. 주로 애니메이션을 부드럽게 실행할 때 사용
  • setTimeout은 지정한 시간간격 , requestAnimationFrame 브라우저의 리프레시 속도(주로 16.67ms, 60FPS)에 맞춰 실행
  • callback은 자동적으로 디스플레이의 주사율에 맞춰서 실행된다는 것이다.
  • requestAnimationFrame을 통해 callback을 실행하면,

사용자가 60hz를 사용하던 144hz를 사용하던 상관없이 사용자의 디스플레이에 맞춰진다.

requestAnimationFrame을 사용하면 페이지가 비활성화인 상태일 때 repaint 작업이 멈춘다.

애니메이션이 일시중지 되므로 CPU 리소스를 낭비하지 않는다.

Event Loop에는 Animation Frames라는 requestAnimationFrame 전용 Queue가 존재한다.

https://developer.mozilla.org/ko/docs/Web/API/Window/requestAnimationFrame

requestAnimationFrame(콜백함수)
export default function Test() {
  const [scale, setScale] = useState(1);

  useEffect(() => {
    let ticking = false;

    const handleScroll = () => {
      if (!ticking) {
        requestAnimationFrame(() => {
          const scrollY = window.scrollY;
          const newScale = 1 + Math.min(scrollY / 500, 0.3); // 최대 1.5배로 설정
          setScale(newScale);
          ticking = false;
        });
        ticking = true;
      }
    };

    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  return (
    <Contents>
      <Empty />
      <TestStyle scale={scale}>
        <img src={Img} />
      </TestStyle>
    </Contents>
  );
}

setTimeout을 활용한 Recursive Polling

  • WebSocket을 사용하기 어려울 때 활용 ⇒ 그러나 네트워크 응답이 느리면 중복 요청이 발생할 수 있고, 서버 부하 증가 문제가 있으니 WebSocket을 고려하는 것이 좋음.
  • 이런게 있다~ 정도
useEffect(() => {
  let isActive = true;

  const fetchData = async () => {
    if (!isActive) return;
		await ~~~함수내용 
    if (isActive) {
      setTimeout(fetchData, 5000); // 5초 후 다시 실행
    }
  };

  fetchData(); // 초기 실행

  return () => {
    isActive = false; // 언마운트 시 정리
  };
}, []);

0개의 댓글