前言
目前在做一个大型的前端后台管理系统,里面有大量的表单校验和输入框查询操作。如果每次用户输入的瞬间都去响应或者检测,其实是不太必要的,因为用户的输入一般具有连续性,所以可以在用户输入产生停顿的时候再去校验或者向服务器发送请求。
解决方案
采用的解决方案是直接使用 lodash
防抖函数 _.debouce
。
详情可以参照: lodash 中文文档
理解防抖
作用:延迟执行,防止间隔时间内连续调用,减少响应次数,优化性能。
自实现代码:
/**
*
* @param {function} func 回调函数
* @param {number} wait 表示时间窗口的间隔
* @param {boolean} immediate 是否立即执行
*
* @return {function} 返回调用函数
*/
var debounce = (func, wait = 100, immediate = false) => {
let timer, ctx, args;
// 延迟执行函数
const later = () => setTimeout(() => {
timer = null;
if (!immediate) {
func.call(ctx, ...args);
ctx = args = null;
}
}, wait);
return function() {
if (!timer) {
timer = later();
if (immediate) {
func.call(this, ...arguments);
} else {
ctx = this;
args = arguments;
}
} else {
clearTimeout(timer);
timer = later();
}
}
}
如果是立即执行(immediate: true)
- 第一次调用,创建一个保护性质的
timer
- 立即执行传入的
func
并且将返回函数的执行上下文绑定到func
中 - 如果达到
wait
时间执行定时器函数,timer
置为null
,等待一个新的调用过程 - 如果没有达到
wait
时间再次调用 - 此时
timer
仍然存在,于是会调用clearTimeout
清除原有定时器,再创建一个新的timer
- 达到了
wait
时间内无法连续调用的情况,这就是为什么说第一次调用创建的timer是一个保护性质的
如果延迟执行(immediate: false)
- 第一次调用,创建一个
timer
- 缓存执行上下文
this
和arguments
- 由于
JS
中的异步机制,就算wait
值为0
,timer
中的函数也会晚于上一步执行 - 如果达到
wait
事件执行定时器函数,拿到的是正确的this
和args
,而非undefined
- 执行完毕后清除当前缓存执行上下文和参数,等待一个新的调用过程
- 如果没有达到
wait
时间再次调用 - 此时
timer
仍然存在,于是会调用clearTimeout
清除原有定时器,再创建一个新的timer
- 达到了在
wait
时间内无法连续调用的结果
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。