防抖 & 节流 的原理及应用场景
函数防抖和函数节流都用于优化事件处理程序,解决短时间内大量触发某函数而导致的性能问题,比如触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或者卡顿的现象,但是二者的业务需求是不一样的。
防抖
- 含义:一个频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。(无论触发多少次,只执行一次)
- 原理:在第一次调用函数时,创建一个定时器,在指定的时间间隔后运行代码;如果代码还没运行时,又触发了该函数,则清除旧的定时器,重新创建新的定时器;如果超过延时执行的时间,代码执行了,则此时已经是第二次触发了。
- 应用场景:频繁操作点赞和取消点赞的时候;search搜索联想,用户在不断输入值时
1 2 3 4 5 6 7 8 9 10
| const debounce = (func, delay) => { let timer = null; return () => { clearTimeout(timer); timer = setTimeout(() => { func(); }, delay) } }
|
- 案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>防抖</title> </head>
<body> <input type="text" name="normal" id="normal"> <script> ~ function() { function ajax(content) { console.log('ajax request' + content); }
function debounce(func, delay) { let timer = null; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, delay) } } let input = document.querySelector("#normal"); debounceTask = debounce(ajax, 1000) input.addEventListener('keyup', (e) => { debounceTask(e.target.value) }) }() </script> </body>
</html>
|
节流
- 含义:一个频繁触发的函数,在规定时间内,函数执行一次后,只有大于设定的执行周期才会执行第二次。(减少触发执行的频率)
- 原理:第一次执行函数的时候,记录函数执行的时间,当下一次执行的时候,比较时间是否还在间隔时间内,如果是则不执行,否则继续执行;
- 应用场景:一般在onresize/mousemove/onscroll等事件中,防止过多的请求造成服务器压力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
const throttle = (func, delay) => { let lastTime = 0; return () => { var nowTime = Date.now(); if (nowTime - lastTime > delay) { method(); lastTime = nowTime; } } } const throttle = (func, delay) => { let canRun = true; return () => { if (!canRun) return; canRun = false; setTimeout(() => { func(); canRun = true; }, delay) } }
|
- 案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>节流</title> </head>
<body> <input type="text" name="normal" id="normal"> <script> ~ function() { function ajax(content) { console.log('ajax request' + content); }
function throttle(func, delay) { let lastTime = 0; return (...args) => { let now = Date.now(); if (now - lastTime > delay) { console.time(); func.call(this, args); console.timeEnd(); lastTime = now; } } } let input = document.querySelector("#normal"); throttleTask = throttle(ajax, 2000) input.addEventListener('keyup', (e) => { throttleTask(e.target.value) }) }() </script> </body>
</html>
|