41. 타이머
41.1 호출 스케줄링
- 호출 스케줄링: 함수를 일정 시간이 경과된 이후에 호출되도록 함수 호출을 예약하기 위해 타이머 함수를 사용하는 것
41.2 타이머 함수
41.2.1 setTimeout / clearTimeout
- setTimeout함수의 콜백함수는 두번째 인수로 전달받은 시간 이후 단 한번 실행되도록 호출 스케줄링 됨
const timeoutId = setTimeout(func|code[, delay, param1, param2, ...]);
// 1초(1000ms) 후 타이머가 만료되면 콜백 함수가 호출됨
setTimeout(() => console.log('Hi!'), 1000);
// 1초(1000ms) 후 타이머가 만료되면 콜백 함수가 호출됨
// 이 때 콜백 함수에 'Lee'가 인수로 전달됨
setTimeout(name => console.log(`Hi! ${name}.`), 1000, 'Lee');
- clearTimeout함수는 호출 스케줄링을 취소함
const timerId = setTimeout(() => console.log('Hi!'), 1000);
clearTimeout(timerId);
41.2.2 setInterval / clearInterval
- setInterval함수의 콜백 함수는 두번째 인수로 전달받은 시간이 경과할 때마다 반복 실행되도록 호출 스케줄링 됨
const timerId = setInterval(func|code[, delay, param1, param2, ...]);
- clearInterval함수는 호출 스케줄링을 취소함
let count = 1;
const timeoutId = setInterval(() => {
console.log(count); // 1 2 3 4 5
if (count++ === 5) clearInterval(timeoutId);
}, 1000);
41.3 디바운스와 스로틀
- 짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러 호출을 방지하는 프로그래밍 기법
41.3.1 디바운스
- 짧은 시간 간격으로 이벤트를 그룹화해서 마지막에 한번만 이벤트 핸들러가 호출되도록 함
...
const debounce = (callback, delay) => {
let timerId;
// debounce함수는 timerId를 기억하는 클로저를 반환
return event => {
if (timerId) clearTimeout(timerId);
timerId = setTimeout(callback, delay, event);
};
};
// debounce함수가 반환하는 클로저가 이벤트 핸들러로 등록됨
// 300ms보다 짧은 간격으로 input 이벤트가 발생하면 콜백함수가
// 호출되지 않다가 300ms동안 input 이벤트가 더 이상 발생하지 않으면 한번만 호출됨
$input.oninput = debounce(e => {
$msg.textContent = e.target.value;
}, 300);
...
- 실무에서는 Underscore의 debounce함수나 Lodash의 debounce함수를 사용하는 것을 권장함
41.3.2 스로틀
- 짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화해서 일정 시간 단위로 이벤트 핸들러가 호출되도록 호출주기를 만듦
...
const throttle = (callback, delay) => {
let timerId;
// throttle함수는 timerId를 기억하는 클로저를 반환함
return event => {
// delay가 경과하기 전에 이벤트가 발생하면 아무것도 하지 않다가
// delay가 경과했을 때 이벤트가 발생하면 새로운 타이머를 재설정함
// 따라서 delay 간격으로 callback이 호출됨
if (timerId) return;
timerId = setTimeout(() => {
callback(event);
timerId = null;
}, delay, event);
};
};
...
$container.addEventListener('scroll', throttle(() => {
$throttleCount.textContent = ++throttleCount;
}, 100));
...
...
- 실무에서는 Underscore의 throttle함수나 Lodash의 throttle함수를 사용하는 것을 권장함