我想稍微改变一下 lodash 的节流功能
I'd like to have a slightly altered behavior for lodash's throttle function
目前,如果将 wait
选项设置为 500,它最多每 500 毫秒触发一次底层函数。
我想要的是,第一次调用它时,它会等待 100 毫秒触发,但随后的调用它只会每 500 毫秒触发一次。然后如果距离上次触发已经超过500毫秒,它会在100毫秒后回到第一次触发。
是否有任何简单的方法来调整或组合一些节流 and/or 去抖功能来创建那种流?
您可以维护一个日期,其中包含最后一次通话的预定时间:
function throttle(fn, initial, cooldown) {
let last = 0;
return function throttled(...args) {
setTimeout(fn, Math.max(0, cooldown + last - (last = Date.now())) || initial, ...args);
}
}
@Jonas Wilms,谢谢你的回答。我不太喜欢 Date
的使用,而且我发现编写节流函数实际上非常简单。一开始我不知道,因为lodash的节流功能是基于他们的debounce函数,他们的debounce函数对我来说有点复杂。
无论如何,我最终写了这个函数,它似乎完成了工作。
export function throttle(fn, ...delays) {
let t1, t2, activeDelay = 0
return function() {
if (t2) {
clearTimeout(t2)
t2 = undefined
}
if (t1) {
return
}
t1 = setTimeout(() => {
fn(...arguments)
t1 = undefined
// Increment the active delay each time
// and then stick with the last one.
activeDelay = Math.min(++activeDelay, delays.length - 1)
// Set a 2nd `Timeout` that resets the
// active delay back to the first one.
t2 = setTimeout(() => {
activeDelay = 0
t2 = undefined
}, delays[activeDelay])
}, delays[activeDelay])
}
}
目前,如果将 wait
选项设置为 500,它最多每 500 毫秒触发一次底层函数。
我想要的是,第一次调用它时,它会等待 100 毫秒触发,但随后的调用它只会每 500 毫秒触发一次。然后如果距离上次触发已经超过500毫秒,它会在100毫秒后回到第一次触发。
是否有任何简单的方法来调整或组合一些节流 and/or 去抖功能来创建那种流?
您可以维护一个日期,其中包含最后一次通话的预定时间:
function throttle(fn, initial, cooldown) {
let last = 0;
return function throttled(...args) {
setTimeout(fn, Math.max(0, cooldown + last - (last = Date.now())) || initial, ...args);
}
}
@Jonas Wilms,谢谢你的回答。我不太喜欢 Date
的使用,而且我发现编写节流函数实际上非常简单。一开始我不知道,因为lodash的节流功能是基于他们的debounce函数,他们的debounce函数对我来说有点复杂。
无论如何,我最终写了这个函数,它似乎完成了工作。
export function throttle(fn, ...delays) {
let t1, t2, activeDelay = 0
return function() {
if (t2) {
clearTimeout(t2)
t2 = undefined
}
if (t1) {
return
}
t1 = setTimeout(() => {
fn(...arguments)
t1 = undefined
// Increment the active delay each time
// and then stick with the last one.
activeDelay = Math.min(++activeDelay, delays.length - 1)
// Set a 2nd `Timeout` that resets the
// active delay back to the first one.
t2 = setTimeout(() => {
activeDelay = 0
t2 = undefined
}, delays[activeDelay])
}, delays[activeDelay])
}
}