Notice
Recent Posts
Recent Comments
Link
솔미는 성장중
lodash의 debounce VS setTimeout으로 직접 debounce 구현 : 각각 언제 적용해야할까? 본문
728x90
lodash는 성능과 안정성이 검증된 라이브러리이고, 다양한 옵션을 제공하고 있기에 대체로는 lodash의 debounce를 사용해도 무관합니다. 하지만 프로젝트를 진행하던 도중 lodash에서 제공하는 debounce를 쓰니 원하는 대로 동작하지 않는 상황이 있었다.
input에 입력을 받고 어느 정도 시간 이상으로 추가입력이 일어나지 않으면 api 호출을 하는 로직이었다.
하지만 api 호출이 내가 생각한 것 보다 여러번 일어나는 이슈가 있어서 직접 setTimeout으로 제어하도록 작업을 해주었다.
[중간에 추가 호출이 있으면 시간 초를 리셋되도록 하고싶다]
function customDebounce(fn, delay) {
let timeoutId;
return function(...args) {
// 기존의 타임아웃을 클리어하여 중간에 호출 시 리셋
if (timeoutId) {
clearTimeout(timeoutId);
}
// 새롭게 타임아웃을 설정
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
// 사용 예시
const debouncedFunction = customDebounce((text) => {
console.log("Search Query:", text);
}, 500);
// 사용자가 타이핑할 때 호출
debouncedFunction("Hello");
// -> 중간에 다른 호출이 있으면 타임아웃이 리셋되고 마지막 입력 후 500ms 동안 입력이 없을 때만 실행
그 외에 다른 방식으로도 커스터마이징 할 수 있다.
[특정 조건에서만 지연 없이 즉시 실행되도록 하고 싶다]
ex. 첫 클릭은 즉시 실행, 나머지는 일정 시간 지연 후에 실행
function conditionalDebounce(fn, delay, immediateCondition) {
let timeoutId;
let initialCall = true;
return function(...args) {
const shouldCallImmediately = typeof immediateCondition === 'function' ? immediateCondition() : immediateCondition;
if (shouldCallImmediately || initialCall) {
fn.apply(this, args);
initialCall = false;
return;
}
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
// 사용 예시
let immediateFlag = false;
const debouncedFunction = conditionalDebounce(
(text) => { console.log("Executed:", text); },
500,
() => immediateFlag // 조건에 따라 즉시 실행
);
// 플래그가 true면 즉시 실행
immediateFlag = true;
debouncedFunction("First Call"); // 즉시 실행
// 플래그가 false면 지연 후 실행
immediateFlag = false;
debouncedFunction("Second Call"); // 지연 후 실행
[debounce와 throttle 둘 다의 효과를 보게 하고 싶다]
ex. 스크롤이 멈추면 마지막 이벤트를 처리한다. 하지만 지나치게 많은 이벤트 실행을 방지하기 위해 호출 간격을 제한해야 하는 경우
function minIntervalDebounce(fn, delay, minInterval) {
let timeoutId;
let lastCallTime = 0;
return function(...args) {
const now = Date.now();
const elapsedTime = now - lastCallTime;
if (timeoutId) {
clearTimeout(timeoutId);
}
if (elapsedTime > minInterval) {
fn.apply(this, args);
lastCallTime = now;
} else {
timeoutId = setTimeout(() => {
fn.apply(this, args);
lastCallTime = Date.now();
}, delay);
}
};
}
// 사용 예시
const debouncedFunction = minIntervalDebounce((event) => {
console.log("Scroll event handled");
}, 200, 1000);
// 스크롤 이벤트 핸들러에 적용
window.addEventListener('scroll', debouncedFunction);
728x90