节流的运用场景和实现
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
前言
节流函数是规定一个单位时间,在这段时间内多次触发的情况都不会生效。
假设我们设置1s执行一次,那么在这一秒钟只会执行一次,当走到下一秒的时候才会触发。
实例
常见的网页中我们或许需要监听网页的滚动,但是这个事件在滚动的过程中触发的过于频繁,为了减少触发次数,就需要使用节流函数来进行限制,使其只在一段时间内执行一次
代码实现
一个普通的节流函数,需要传递节流的函数和延迟时间,在我们执行函数的时候开启一个定时器,并创建一个 canRun 变量,当定时器执行完毕之后才能开启函数的再次执行,代码如下:
function throttle(func, wait = 500) {
let canRun = true
if (typeof func !== 'function')
throw new TypeError(`Expected a function, got ${typeof func}`)
return function () {
const that = this
const args = arguments
if (canRun) {
canRun = false
setTimeout(() => {
func.apply(that, args)
canRun = true
}, wait)
}
}
}
上面只是简单的实现了一个节流函数,从代码可以看出,函数执行之后不会立即执行我们需要执行的函数,如果我们想要立即执行该如何处理呢?
立即执行
我们只需要传递一个控制变量,进入的时候立即执行函数就可以完成该功能。
function throttle(func, wait = 500, options) {
let canRun = true
const leading = options.leading ?? true // 立即执行
if (typeof func !== 'function')
throw new TypeError(`Expected a function, got ${typeof func}`)
return function () {
const that = this
const args = arguments
if (canRun) {
canRun = false
clearTimeout(timer)
leading && func.apply(that, args)
setTimeout(() => {
!leading && func.apply(that, args)
canRun = true
}, wait)
}
}
}
加大难度,如何确保节流函数最后一次一定执行呢?
尾执行
首先需要明白一件事情,想要确保最后一次执行,那么在点击的时候 canRun一定是false,在这个时候可以开启 else 分支,开启一个定时器,来确保最后一次执行。
当然,如果不是最后一次我们需要清除这个定时器,在进入函数的时候我们就要清除这个定时器,把下一次定位最后一次。
function throttle(func, wait, options) {
let canRun = true
const leading = options.leading ?? true // 立即执行
const trailing = options.trailing ?? true // 尾执行
let timer = null
if (typeof func !== 'function')
throw new TypeError(`Expected a function, got ${typeof func}`)
return function () {
const that = this
const args = arguments
clearTimeout(timer)
if (canRun) {
canRun = false
leading && func.apply(that, args)
setTimeout(() => {
!leading && func.apply(that, args)
canRun = true
}, wait)
}
else {
if (trailing) {
timer = setTimeout(() => {
func.apply(that, args)
}, wait)
}
}
}
}