호출 스케줄링이란(scheduling a call), 함수를 명시적으로 호출하지 않고 타이머 함수를 사용하여 일정 시간이 경과된 이후에 함수가 호출되도록 예약하는 것을 말한다.
타이머 함수는 ECMAScript 사양에 정의된 빌트인 함수가 아니라 호스트 객체이다.
자바스크립트는 타이머를 생성할 수 있는 타이머 함수 setTimeout과 setInterval, 타이머를 제거할 수 있는 타이머 함수 clearTimeout과 clearInterval을 제공한다.
자바스크립트 엔진은 단 하나의 실행 컨텍스트 스택을 갖기 때문에 싱글 스레드(single thread)로 동작한다.
따라서 타이머 함수 setTimeout과 setInterval은 비동기(asynchronous) 처리 방식으로 동작한다.
setTimeout 함수는 두 번째 인수로 전달받은 시간[ms]으로 단 한 번 동작하는 타이머를 생성하고, 이후 만료되면 첫 번째 인수로 전달받은 콜백 함수가 단 한 번 호출된다.
const timerId = setTimeout(func|code[, delay, param1, param2, ...]);
setTimeout 함수는 생성된 타이머를 식별할 수 있는 고유한 타이머 id를 반환하며, 반환된 id를 clearTimeout 함수의 인수로 전달하여 타이머를(호출 스케줄링을) 취소할 수 있다.
const timerId = setTimeout(() => console.log('Hardy'), 1000);
clearTimeout(timerId);
setInterval 함수는 두 번째 인수로 전달받은 시간[ms]으로 반복 동작하는 타이머를 생성하고, 이후 타이머가 취소될 때까지 타이머가 만료될 때마다 첫 번째 인수로 전달받은 콜백 함수가 반복 호출된다.
setInterval 함수에 전달할 인수는 setTimeout 함수와 동일하다.
const timerId = setInterval(fun|code[, delay, param1, param2, ...]);
setTimeout 함수와 마찬가지로, setInterval 함수도 생성된 타이머를 식별할 수 있는 고유한 타이머 id를 반환하며, 반환된 id를 clearInterval 함수의 인수로 전달하여 타이머를(호출 스케줄링을) 취소할 수 있다.
let count = 1;
const timerId = setInterval(() => {
console.log(count);
if (count++ === 5) clearInterval(timerId);
}, 1000)
짧은 시간 간격으로 연속해서 발생하는 이벤트의 경우, 이벤트에 바인딩한 이벤트 핸들러가 과도하게 호출되어 성능에 좋지 않은 영향을 끼칠 수 있다.
디바운스와 스로틀은 짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법이다.
디바운스와 스로틀은 이벤트를 처리할 때 매우 유용하며, 디바운스/스로틀 구현에는 타이머 함수가 사용된다.
디바운스(debounce)는 짧은 시간 간격으로 이벤트가 연속해서 발생하면 이벤트 핸들러를 호출하지 않고 그룹화한 다음, 일정 시간이 경과한 이후에 이벤트 핸들러가 한 번만 호출되도록 한다.
모던 자바스크립트 Deep Dive, p.806, 그림 41-2 참조
<aside> <img src="/icons/chat_gray.svg" alt="/icons/chat_gray.svg" width="40px" /> 디바운스는 resize 이벤트 처리나 Input 요소에 입력된 값으로 Ajax 요청하는 입력 필드 자동완성 UI 구현, 버튼 중복 클릭 방지 처리 등에 유용하게 사용된다. 또한 실무에서는 Underscore의 debounce 함수나 Lodash의 debounce 함수를 사용하는 것을 권장한다.
</aside>
[https://underscorejs.org/docs/modules/debounce.html](https://underscorejs.org/docs/modules/debounce.html)