갑자기 debouncing, throttling 을 직접 만들어 보고 싶었습니다. 클로저와 고차 함수를 사용하면 될 것 같았습니다. 쓸일은 없을것 같지만 ㅎㅎ
type Debounce = (...args: any[]) => void;
// 콜백함수와 딜레이를 인자로 받는 HOC
const debounce = (func: (...args: any[]) => void, delay: number): Debounce => {
let timer : NodeJS.Timeout | null = null; // 클로저로 유지될 변수(타이머)
return (...args : any[]) => {
if(timer !== null) clearTimeout(timer); // 이전 타이머가 있으면 취소
timer = setTimeout(() => {
func(...args); // 일정시간 후 실행, this 참조 대비하여 apply
}, delay);
};
}
// HOC 에 함수와 딜레이를 넣어서 호출
const handleInput: Debounce = debounce(() => {
console.log('API 호출');
}, 300);
document.querySelector('input').addEventListener('input', handleInput);
type Throttle = (...args: any[]) => void;
// 콜백함수와 리미트를 인자로 받는 HOC
const throttle = (func: (...args: any[]) => void, limit: number): Throttle => {
let lastTimer: NodeJS.Timeout | null = null; // 클로저로 유지될 변수(타이머)
let lastRan: number | null = null; // 클로저로 유지될 변수(마지막 실행시점)
return (...args: any[]) => {
if(lastRan !== null){
func(...args); // 처음 호출될 때 바로 실행
lastRan = Date.now(); // 마지막 실행 시점을 현재 시간으로 기록
return;
}
if(lastTimer !== null) clearTimeout(lastTimer); // 이전에 설정된 타이머 취소
lastTimer = setTimeout(() => {
if((Date.now() - lastRan) >= limit) { // 제한 시간 이후에만 실행
func(...args); // 콜백함수 실행
lastRan = Date.now(); // 마지막 실행 시점 업데이트
}
}, limit - (Date.now() - lastRan))
// 위 setTimeout의 2번째 인자 부분은,
// 마지막으로 함수가 실행된 시점(lastRan)에서 얼마나 시간이 지났는지 계산하여,
// 정확히 limit 간격만큼 대기한 후에 함수를 실행시키기 위한 계산임
};
}
// HOC 에 함수와 리미트를 넣어서 호출
const handleScroll: Throttle = throttle(() => {
console.log("스크롤 이벤트 처리");
}, 1000);
window.addEventListener("scroll", handleScroll);