什么是节流
在计算机编程尤其是前端开发领域,"节流"(Throttling)是一种优化技术,用于控制函数的调用频率,以避免在短时间内因高频触发事件而导致的性能问题。具体来说,节流保证一个函数在特定的时间间隔内只执行一次,即使在这段时间内事件被触发多次。这种方式可以有效减少如滚动事件、窗口大小调整(resize)等连续且频繁触发的操作对性能的影响,从而提升用户体验和应用的响应速度。
节流的基本原理是使用定时器。当第一次事件触发时,会立即执行函数,并设置一个定时器,在指定的时间间隔之后才能再次触发该函数。如果在这段时间内又有新的事件触发,定时器会被重置,从而保证从最后一次触发事件开始,至少要等待预设的时间间隔后,函数才会被执行。这样,无论事件触发多么频繁,函数的实际执行频率都被限制住了。
节流的实现
html
<div class="row">
<div>
没有节流的input <input type="text" id="inputa" />
</div>
<div>
节流后的input <input type="text" id="inputc" />
</div>
</div>
- 非节流状态的JavaScript代码
每次在输入框输入内容,就会触发ajax函数
javascript
const inputa = document.getElementById('inputa');
const ajax = (content) => {
console.log(`ajax request ${content}`);
}
ajax(content)
:模拟一个耗时的网络请求操作,这里简单地输出到控制台。 可以看到右边的输出,只要我输入一次,就会执行一次,在大型项目中,我们要规避,要优化代码的性能
- 节流状态的JavaScript代码
ini
const inputa = document.getElementById('inputa');
const inputc = document.getElementById('inputc');
const ajax = (content) => {
console.log(`ajax request ${content}`);
}
// 节流功能
const throttle = (func, delay) => {
let last, deferTimer;
return (args) => {
let now = +new Date();
if (last && now - last < delay) {
clearTimeout(deferTimer)
deferTimer =setTimeout(() => {
last = now
func(args)
},delay)
} else {
last = now;
func(args);
}
}
}
throttle(func, delay)
:定义节流函数,接收一个待执行的函数func
和延迟时间delay
作为参数。 这里我们考虑到一个问题,用户在最后一次输入时,刚好是在一个delay时间之内,那不就不会输出最后输入的值
所以要在if条件中添加一个清除函数,让程序可以保留用户的最后一次输入,实现不遗漏的执行
ini
const inputa = document.getElementById('inputa');
const inputc = document.getElementById('inputc');
const ajax = (content) => {
console.log(`ajax request ${content}`);
}
// 节流功能
const throttle = (func, delay) => {
let last, deferTimer;
return (args) => {
let now = +new Date();
if (last && now - last < delay) {
clearTimeout(deferTimer)
deferTimer =setTimeout(() => {
last = now
func(args)
},delay)
} else {
last = now;
func(args);
}
}
}
- 闭包中的
last
和deferTimer
:last
用于存储上一次执行的时间戳,deferTimer
则用于管理定时器。
最后就是事件监听的绑定
ini
inputa.addEventListener('keyup', (e) => {
ajax(e.target.value);
});
let throttledFunc = throttle(ajax, 1000);
inputc.addEventListener('keyup', (e) => {
let value = e.target.value;
throttledFunc(value);
});
inputa
上的keyup
事件直接调用ajax
函数,无任何节流处理。inputc
上的keyup
事件则调用经过节流处理的函数throttledFunc
,确保在1秒内最多只发送一次网络请求。
自此我们就完成了节流的实现
结语
防抖和节流是在面试中面试官提问频率最高的问题之二,从细节上去解释,可以让你在面试官的印象里比其他竞争者更加有优势。