节流throttle
可以这么比喻,节流就是游戏中技能cd,立即释放后需要等待cd结束才能再次释放
简易版实现如下:
const throttle = (f, time) => {
let timer = null;
return (...args) => {
if (timer) {
return;
}
f.apply(undefined, args);
timer = setTimeout(() => {
timer = null;
}, time);
};
};
节流的业务常见场景
- 经常用在用户频繁点击按钮,如每五秒钟点一次抢购
- drag和scroll期间触发某个回调,要设置一个时间间隔
防抖debounce
可以这么比喻,防抖就是游戏中回城被打断,需要重新回城等待回城条结束并不被打断才能继续成功回城,简易版代码如下:
const debounce = (f, time) => {
let timer = null;
return (...args) => {
if (timer) {
clearTimeout(timer); //打断回城
}
//重新回城
timer = setTimeout(() => {
f.apply(undefined, args);
timer = null;
}, time);
};
};
防抖的业务常见场景
- 页面修改大小的时候,重新定位,每次拖动打断,拖动结束停留3秒后就resize
- 搜索框打字停止一两秒时候才开始提前搜索关键词
答案
- 节流:限制执行频率,有节奏的执行
- 防抖:限制执行次数,多次密集的触发只执行一次
- 节流关注过程,防抖关注结果
划重点
- 过程(限制频率) vs 结果
- 实际工作用lodash loadsh.com/
具体案例演示代码
- 节流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p>throttle 节流</p>
<div id="div1" draggable="true" style="width: 100px; height: 100px; background-color: aqua; padding: 10px"></div>
<script>
function throttle(fn, delay = 200) {
let timer = null
return function () {
if (timer) return
fn.apply(this, arguments)
timer = setTimeout(() => {
timer = null
}, delay)
}
}
const div1 = document.getElementById('div1')
div1.addEventListener(
'drag',
throttle((e) => {
console.log('鼠标的位置', e.offsetX, e.offsetY)
})
)
</script>
</body>
</html>
- 防抖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p>debounce 防抖</p>
搜索<input id="input1" />
<script>
function debounce(fn, delay = 200) {
let timer = null
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
const input1 = document.getElementById('input1')
input1.addEventListener(
'keyup',
debounce(() => {
console.log('发起搜索', input1.value)
}),
300
)
</script>
</body>
</html>