返回
TDD实践:每天5分钟防抖一记,手把手教你实现防抖防闪
前端
2023-11-08 18:28:20
前言
各位技术爱好者,大家好!我是技术探索领域的领航者,wheelcat。今天,我们踏上了一段TDD实践之旅,每天仅需5分钟,我们将深入浅出地剖析大厂笔试和面试中的必备手写题目。而今天,我们的目标是征服防抖,实现手写防抖防闪的壮举!
防抖的奥义
防抖,顾名思义,就是在频繁触发的事件中,仅在满足一定时间间隔后才执行响应函数。其精髓在于抑制快速、连续的事件触发,确保在一定时间窗口内只执行一次响应函数。
防抖实现实战
让我们用TDD的方式,一步步实现防抖功能。
Step 1:定义需求
type DebouncedFunction = (this: any, ...args: any[]) => any;
// 防抖函数接口
interface DebounceOptions {
// 防抖时间间隔,单位毫秒,默认为0,表示不防抖
wait?: number;
}
// 防抖函数
function debounce(func: DebouncedFunction, options?: DebounceOptions): DebouncedFunction;
Step 2:编写测试用例
describe('debounce', () => {
it('should delay function execution', () => {
const spy = jest.fn();
const debounced = debounce(spy, { wait: 100 });
debounced();
expect(spy).not.toHaveBeenCalled();
});
it('should execute function after wait period', () => {
const spy = jest.fn();
const debounced = debounce(spy, { wait: 100 });
debounced();
setTimeout(() => {
expect(spy).toHaveBeenCalledTimes(1);
}, 100);
});
it('should execute function only once within wait period', () => {
const spy = jest.fn();
const debounced = debounce(spy, { wait: 100 });
debounced();
debounced();
setTimeout(() => {
expect(spy).toHaveBeenCalledTimes(1);
}, 100);
});
});
Step 3:实现防抖函数
function debounce(func: DebouncedFunction, options?: DebounceOptions): DebouncedFunction {
let timeoutId: number | null = null;
return function (this: any, ...args: any[]) {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
func.apply(this, args);
timeoutId = null;
}, options?.wait ?? 0);
};
}
Step 4:验证测试用例
运行测试用例,确保所有断言均通过。
恭喜!你已经成功实现了手写防抖函数。
防闪优化
防闪,是防抖的一种特殊情况,适用于连续触发事件的情况。在防闪场景下,当触发事件的频率高于防抖时间间隔时,响应函数只会在事件停止触发后的指定时间间隔内执行一次。
防闪实现实战
Step 1:修改需求
// 防闪选项
interface DebounceWithLeadingOptions extends DebounceOptions {
// 是否开启防闪,默认为false,即不开启
leading?: boolean;
}
// 防闪函数
function debounce(func: DebouncedFunction, options?: DebounceWithLeadingOptions): DebouncedFunction;
Step 2:编写测试用例
describe('debounce', () => {
it('should execute function immediately if leading is true', () => {
const spy = jest.fn();
const debounced = debounce(spy, { leading: true, wait: 100 });
debounced();
expect(spy).toHaveBeenCalledTimes(1);
});
it('should execute function only once within wait period even with leading', () => {
const spy = jest.fn();
const debounced = debounce(spy, { leading: true, wait: 100 });
debounced();
debounced();
setTimeout(() => {
expect(spy).toHaveBeenCalledTimes(1);
}, 100);
});
});
Step 3:实现防闪
在原有防抖函数的基础上进行修改:
function debounce(func: DebouncedFunction, options?: DebounceWithLeadingOptions): DebouncedFunction {
let timeoutId: number | null = null;
let leadingCall = options?.leading ?? false;
return function (this: any, ...args: any[]) {
if (timeoutId) {
clearTimeout(timeoutId);
}
if (leadingCall) {
func.apply(this, args);
leadingCall = false;
}
timeoutId = setTimeout(() => {
func.apply(this, args);
timeoutId = null;
}, options?.wait ?? 0);
};
}
Step 4:验证测试用例
运行测试用例,确保所有断言均通过。
太棒了!你已经成功实现了手写防闪函数。
进阶思考
防抖和防闪是前端开发中的常见技术,广泛应用于各种场景。掌握防抖和防闪技巧,不仅能提升代码质量,还能提升用户体验。
在实际应用中,可以根据需要灵活选择是否开启防闪,并调整防抖时间间隔,以达到最佳效果。
欢迎在评论区分享你的经验和心得,与其他技术爱好者共同探索技术奥秘!