- 防抖
- 节流
- 如何处理防抖与节流
- 防抖
- 节流
- 防抖例子
- 节流例子
- Vue + Axios全局接口防抖、节流封装实现
- 小结
防抖
防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
应用场景: 提交按钮、用户注册时候的手机号验证、邮箱验证
假设我们有一个登录按钮,如果用户在短时间内多次点击登录按钮,防抖技术可以防止系统误认为这是多次登录请求,而只将其视作一次有效的登录操作。
节流
节流:高频事件触发,但在n秒内只会执行一次,所以 节流会稀释函数的执行频率。
应用场景: window对象的resize、scroll事件 拖拽时候的mousemove 射击游戏中的mousedown、keydown事件 文字输入、自动完成的keyup事件
在窗口调整、页面滚动或者抢购等场景中,我们可能就需要使用节流来控制事件的执行频率,以防止资源的浪费。
更多详细内容,请微信搜索“前端爱好者
“, 戳我 查看 。
如何处理防抖与节流
防抖和节流是两种常见的优化技术,用于防止函数被过度调用。
防抖
对于 防抖 ,可以采用以下方式进行处理:
在函数被触发后,先不立即执行函数,而是设置一个 延迟时间,比如n秒。
如果在延迟时间内再次触发了该函数,则重新计算执行时间。只有在延迟时间内没有再次触发函数,才执行函数。
节流
对于节流,可以采用以下方式进行处理:
同样在函数被触发后,先不立即执行函数,而是设置一个时间间隔,比如每n秒执行一次函数。
这样无论函数被触发的频率有多高,只有每n秒内的第一次触发会被执行。
具体实现防抖和节流的代码,可以参考以下示例代码:
// 防抖
function debounce(fn, delay) { let timer = null; return function() { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, arguments); }, delay); };
}
在防抖函数中,我们首先定义了一个定时器变量 timer。
在函数被触发时,先清除上一次的定时器,然后设置一个新的定时器,延迟指定时间后执行函数 fn。
这样就实现了在一段时间内只执行一次函数的效果。
// 节流
function throttle(fn, delay) { let timer = null; return function() { if (!timer) { timer = setTimeout(() => { fn.apply(this, arguments); timer = null; }, delay); } };
}
在节流函数中,我们同样定义了一个定时器变量 timer。
在函数被触发时,检查定时器是否已经存在,如果不存在,则设置一个新的定时器,延迟指定时间后执行函数 fn。
这样就实现了在一段时间内只执行一次函数的效果。
防抖例子
对于短时间内频繁点击或输入的事件触发,未使用防抖处理的事件对于用户体验并不是很好。因此我们可以使用防抖进行处理,如下:
<div class="box">进行防抖处理的:<input type="text" id="name" name="name">
</div>
<script>// 模仿一段ajax请求function ajax(value){console.log("ajax request: " + value + ", time: " + new Date());}// 防抖函数function debounce(func,delay){let timeout; //定时器return function(arguments){// 判断定时器是否存在,存在的话进行清除,重新进行定时器计数if(timeout) clearTimeout(timeout);//清除之前的事件timeout = setTimeout(()=>{func.call(this,arguments);//执行事件},delay);}}const inputBox = document.getElementById("name");// 使用防抖函数进行封装ajaxlet debounceAjax = debounce(ajax,500);inputBox.addEventListener("keyup",e=>{debounceAjax(e.target.value);})
</script>
从上面的运行结果可以看出,在500ms内输入文字按下键盘都不会触发请求事件,而是在输入框的定时器500ms停止输入后发送请求。
实现原理很简单,就是对于频繁输入的输入框请求事件添加定时器进行计数,在指定时间内进行频繁输入并不会进行ajax请求,而是在指定时间间隔内停止输入才会执行函数。
当停止输入但在此定时器计数时间内,会重新进行触发请求事件
节流例子
<div class="box">进行节流处理的:<input type="text" id="name" name="name">
</div>
<script>// 模仿一段ajax请求function ajax(value){console.log("ajax request: " + value + ", time: " + new Date());}// 节流--定时器版function throttle(func,delay){let timeout;//定义一个定时器标记return function(arguments){// 判断是否存在定时器if(!timeout){ // 创建一个定时器timeout = setTimeout(()=>{// delay时间间隔清空定时器clearTimeout(timeout);func.call(this,arguments);},delay)}}}const inputBox = document.getElementById("name");// 使用节流函数进行封装ajaxlet throttleAjax = throttle(ajax,500);inputBox.addEventListener("keyup",e=>{throttleAjax(e.target.value);})
</script>
从上面可以看到,无论我们在输入框输入多少文字,在指定时间内只执行一次函数
Vue + Axios全局接口防抖、节流封装实现
import axios from 'axios'function request(config) {const instance = axios.create({baseURL: 'http://localhost:3000/api',timeout: 10000})// 防抖const debounceTokenCancel = new Map()instance.interceptors.request.use(config => {const tokenKey = `${config.method}-${config.url}`const cancel = debounceTokenCancel.get(tokenKey)if (cancel) {cancel()}return new Promise(resolve => {const timer = setTimeout(() => {clearTimeout(timer)resolve(config)}, 800)debounceTokenCancel.set(tokenKey, () => {clearTimeout(timer)resolve(new Error('取消请求'))})})}, error => {console.log(error)return Promise.reject(error)})instance.interceptors.response.use(response => {return response}, error => {console.log(error)return Promise.reject(error)})// 节流let lastTime = new Date().getTime()instance.interceptors.request.use(config => {const nowTime = new Date().getTime()if (nowTime - lastTime < 1000) {return Promise.reject(new Error('节流处理中,稍后再试'))}lastTime = nowTimereturn config}, error => {console.log(error)return Promise.reject(error)})return instance(config)
}export default request
小结
- 函数防抖和函数节流都是防止某一时间内频繁触发。
- 函数防抖是在指定时间只执行一次,而函数节流是每到指定间隔时间执行一次。
- 函数防抖是将几次操作合并为一此操作进行,函数节流使得一定时间内只触发一次函数。
参考链接
- https://blog.csdn.net/qq_40716795/article/details/123144385
- https://juejin.cn/post/7225133152490160187