- 防抖
- 节流
- 如何处理防抖与节流
- 防抖
- 节流
- 防抖例子
- 节流例子
- 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");
// 使用防抖函数进行封装ajax
let 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");
// 使用节流函数进行封装ajax
let 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 = nowTime
return 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