타이머 함수
자바스크립트는 타이머를 생성할 수 있는 setTimeout, setInterval 타이머 함수를 제공하고, 해당 타이머 함수를 통해 생성한 타이머를 제거할 수 있는 clearTimeout과 clearInterval 함수를 제공한다. 이 타이머 함수는 빌트인 함수가 아니고, 브라우저와 Node.js 환경에서 전역 객체의 메서드로 제공하는 호스트 객체이다.
setTimeout / clearTimeout
setTimeout 타이머 함수는 두 번째 인수로 ms 단위의 시간을 전달받는데, 인수로 전달받은 시간으로 단 한 번만 동작하는 타이머를 생성한다. 이 후 두 번째 인수로 전달한 시간이 지나고 타이머가 만료되면 첫 번째 인수로 전달한 콜백 함수가 호출된다.
setTimeout((name) => console.log(`Hi ${name}`), 1000, 'Kim')
// Hi Kim
세 번째 인수부터는 콜백 함수에 전달해야할 인수를 전달한다.
setTimeout 타이머 함수는 생성된 타이머를 식별할 수 있는 고유의 타이머 id를 반환한다. 브라우저 환경인 경우 반환한 타이머 id는 숫자이고, Node.js 환경인 경우 객체이다. 따라서 setTimeout 함수가 반환한 타이머 id를 clearTimeout 함수의 인수로 전달하여 타이머를 취소하는 것이 가능하다.
const timerId = setTimeout((name) => console.log(`Hi ${name}`), 1000, 'Kim');
clearTimeout(timerId); // 호출 스케줄링 취소
setInterval / clearInterval
setInterval 타이머 함수는 두 번째 인수로 ms 단위의 시간을 전달받는데, 인수로 전달받는 시간으로 반복 동작하는 타이머를 생성한다. 이 후 두 번째 인수로 전달한 시간이 지나 타이머가 만료될 때마다 첫 번째 인수로 전달한 콜백 함수가 반복적으로 호출된다. 콜백함수는 타이머가 취소될 때 까지 계속해서 반복 실행된다.
let count = 1
const timerId = setInterval(() => {
console.log(count)
if(count++ === 5) clearInterval(timerId)
}, 1000)
count가 1초마다 count를 출력하고 count가 5가 되었을 때 setInterval이 반환한 타이머 id를 clearInterval 함수의 인수로 전달하여 타이머를 취소한다.
디바운스와 스로틀
특정 이벤트에 이벤트 핸들러를 바인딩 한 경우 scroll, resize, input, mousemove와 같은 이벤트는 굉장히 짧은 시간동안 연속적으로 이벤트가 발생하는데, 이렇게 과도하게 이벤트가 호출되는 경우는 성능에 큰 영향을 미친다. 따라서 짧은 시간동안 연속적으로 발생하는 이벤트에 한하여 해당 이벤트를 그룹화해서 과도한 이벤트의 호출을 제어하는 방법을 디바운스와 스로틀이라고 한다.
디바운스
디바운스는 일정 시간동안 이벤트가 연속적으로 호출될 때, 마지막 이벤트 이후 일정 시간이 지나면 한번만 이벤트 핸들러를 실행한다.
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" />
<div class="msg"></div>
<script>
const $input = document.querySelector("input");
const $msg = document.querySelector(".msg");
$input.oninput = (e) => {
$msg.textContent = e.target.value;
};
</script>
</body>
</html>
디바운스를 적용하지 않았을 때는 input의 value가 변화할 때마다 msg 클래스를 가지는 요소의 textContent에 해당 value로 변경하고 있다.
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" />
<div class="msg"></div>
<script>
const $input = document.querySelector("input");
const $msg = document.querySelector(".msg");
const debounce = (callback, delay) => {
let timerId;
return (e) => {
if (timerId) clearTimeout(timerId);
timerId = setTimeout(callback, delay, e);
};
};
$input.oninput = debounce((e) => {
$msg.textContent = e.target.value;
}, 1000);
</script>
</body>
</html>
delay가 경과하기 이전에 이벤트가 추가적으로 발생한다면 이전 타이머를 clearTimeout을 통해 취소하고 새로운 타이머를 재설정하기 때문에 1000ms 동안 이벤트가 발생하지 않는경우 호출된다.
스로틀
스로틀은 짧은 간격으로 이벤트가 연속해서 발생하는 경우 일정 시간 간격으로 이벤트 핸들러가 최대 한 번만 호출되도록 한다.
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" />
<div class="msg"></div>
<script>
const $input = document.querySelector("input");
const $msg = document.querySelector(".msg");
const throttle = (callback, delay) => {
let timerId;
return (event) => {
if (timerId) return;
timerId = setTimeout(
() => {
callback(event);
timerId = null;
},
delay,
event
);
};
};
$input.oninput = throttle((event) => {
$msg.textContent = event.target.value;
}, 1000);
</script>
</body>
</html>
delay가 경과하기 이전에 이벤트가 발생하면 아무것도 하지않다가 delay가 경과했을 때 이벤트가 발생하면 새로운 타이머를 재설정한다. 따라서 delay 시간 간격으로 callback이 호출된다.
'개발 지식 정리 > Javascript' 카테고리의 다른 글
requestAnimationFrame (0) | 2023.08.30 |
---|---|
이벤트 루프 (0) | 2023.07.21 |
DOM (0) | 2023.07.14 |
이터러블 (0) | 2023.07.11 |
클래스 (0) | 2023.07.05 |