🙆🏻‍♀️ setTimeout & setInterval 🙆🏻‍♀️

일정 시간 후에 원하는 함수를 실행할 수 있는 setTimeout.
일정 시간 간격을 두고 함수를 실행할 수 있는 setInterval.
정도로만 알고 있었던 두 Web API.

"내가 너무 대충 알고 있었구나." 깨닫게 되면서 자세히 알아보는 시간을 가졌다.
더불어 자바스크립트 런타임에 대한 이해도도 높이고, requestAnimationFrame도 알게 됐다. (머쓱머쓱^^;)

setTimeout

// 기본 문법
let timer = setTimeout(func|code, [delay], [arg1...], [arg2...], ...);
  • func|code: 실행하고자 하는 함수 또는 문자열을 넣는 자리. 하위 호환성을 위해 문자열도 받을 수 있게 해놓았지만,(js는 이 문자열을 이용해 함수를 만든다) 주로 함수를 사용한다.
  • delay: 실행 전 대기 시간으로, 단위는 밀리초(ms)이다. 기본값은 0이며 입력한 시간은 최소 보장 시간이다.
  • arg1, arg2, ...: 함수에 인수를 전달할 수도 있다. (IE9 이하에선 지원하지 않는다고 하는데 이제... IE 27년만에 역사 속으로... 나때는 말이야! 브라우저마다 처리를 다르게 해줘야 했다고~☆)
// 사용법
function test(name) {
  console.log(`${name}씨, 계세요...?`)
}

setTimeout(test, 1000, "코난"); // 코난씨, 계세요...?

setTimeout을 취소하고 싶을 때는, clearTimeout을 사용한다.

setInterval

// 기본 문법
let timer = setInterval(func|code, [delay], [arg1...], [arg2...], ...);

setInterval은 setTimeout과 동일한 문법을 사용한다.
다만 주기적으로 함수를 실행하는데 이것을 중단하고 싶을 때는, clearInterval을 사용한다.
따로 종료 조건을 넣지 않으면 무한히 실행되기 때문에 꼭! 함수 내에 조건을 넣어서 clearInterval을 사용해주자.

중첩 setTimeout

setTimeout을 중첩하여 setInterval과 같이 주기적으로 함수를 실행할 수도 있다.

let timer = setInterval(() => console.log("똑똑똑"), 1000);


let timer2 = setTimeout(function knock() {
  console.log("똑똑똑");
  timerId = setTimeout(knock, 1000);
}, 1000);

왜 굳이 중첩 setTimeout을 쓸까?
첫 번째, 중첩 setTimeout은 시간을 조정할 수 있다.

// 시간 조정 가능!!!
let delay = 1000;

let timer = setTimeout(function request() {
  //무언가를 요청

  if (그 요청이 실패했다면?) {
    // 요청 간격을 늘린다.
    delay *= 2;
  }

  timer = setTimeout(request, delay);

}, delay);

두 번째, 지연 간격을 보장할 수 있다.

// 지연 간격 보장!!!
let i = 1;
setInterval(function() {
  func(i++);
}, 100);

//

let i = 1;
setTimeout(function run() {
  func(i++);
  setTimeout(run, 100);
}, 100);

setIntercval을 사용하면 예시의 fun을 실행하는 시간도 지연 간격에 포함 시킨다.
그래서 fun의 실행 시간이 명시한 지연 시간보다 길다면, fun 실행 종료를 기다려줬다가 바로 다음 호출을 시작한다.

하지만, 중첩 setTimeout은 이전 함수 실행 종료 후에 다음 함수를 호출할 계획이 세워지기 때문에 지연 간격이 보장된다.


최소 시간 보장

앞서 매개변수중 delay를 설명할 때, 최소 시간 보장이란 말을 썼다.
정확히 delay 시간 후에 원하는 함수가 실행되는 것이 아니기 때문이다.

function test(name) {
  console.log(`${name}씨, 계세요...?`)
}

setTimeout(test, 5000, "코난"); // 코난씨, 계세요...?

setTimeout이 실행되면 test 함수는 Web APIs영역에서 5000ms의 시간을 보낸 뒤, Task Queue에 담긴다.
이벤트 루프는 빙글 빙글 돌면서 Call Stack과 Queue들의 상태를(Task Queue, Microtask Queue, RAF Queue 등) 확인한다. (JS 런타임 참고...)
Call Stack이 비워졌다면 Task Queue에 담긴 test가 실행 되면서 "코난씨, 계세요...?"가 콘솔에 찍힌다.
만약 콜 스택에 담긴 것이 있다면 5초가 지난 후에도 콘솔은 찍히지 않는다.

requestAnimationFrame

requestAnimationFrame은 애니메이션 구현에 최적화된 함수다. 60Hz라면 1초에 60번 호출한다. (웹 브라우저는 디스플레이의 Hz를 따른다.)

setInterval처럼 스스로 반복해서 호출하지 않기 때문에 requestAnimationFrame은 callback 내에서 재호출하여 사용하여야 한다.

// 사용법
let t = 60;

const callback = () => {
   console.log('callback', t--);
   t && requestAnimationFrame(callback);
}

requestAnimationFrame(callback);
  • callback: 다음 리페인트 과정이 전에 실행할 함수를 인자로 받는다.
    이벤트를 취소하고 싶을 때는 cancelAnimationFrame을 사용한다.

자바스크립트로 애니메이션을 구현할 때는 requestAnimationFrame을 우선으로 생각해보자.

Queue의 실행 순서

Microtask Queue -> RAF Queue -> Task Queue

setTimeout과 setInterval을 이용한 호출 스케줄링 - 코어 자바스크립트

profile
당당하게 외치고 싶어요. "나, 「프런트엔드 개발자」야" 라고...😏

0개의 댓글