Das Zusammenführen von Debounce und Throttle kann sehr verwirrend sein, da sie beide einen Parameter namens delay
teilen.
Debounce. Das delay
ist darauf ausgelegt zu warten, bis keine weiteren Aufrufe mehr erfolgen, um es dann aufzurufen. Ähnlich wie das schließen einer Aufzugstür: Die Tür muss warten, bis niemand mehr versucht einzusteigen, bevor sie sich schließt.
Throttle. Das delay
besteht darin, mit einer Frequenz zu warten und dann für den letzten Aufruf zu sorgen. Ähnlich wie beim Abfeuern einer Pistole, die Waffe kann einfach nicht über eine bestimmte Rate hinaus abgefeuert werden.
Lassen Sie uns die Implementierung im Detail betrachten.
function debounce(fn, delay) {
let handle = null
return function () {
if (handle) {
handle = clearTimeout(handle)
}
handle = setTimeout(() => {
fn(...arguments)
}, delay)
}
}
Debounce unterbricht ständig den Timeout, bis keine Unterbrechungen mehr erfolgen, und ruft dann fn
auf.
function throttle(fn, delay) {
let handle = null
let prevArgs = undefined
return function() {
prevArgs = arguments
if (!handle) {
fn(...prevArgs)
prevArgs = null
handle = setInterval(() => {
if (!prevArgs) {
handle = clearInterval(handle)
} else {
fn(...prevArgs)
prevArgs = null
}
}, delay)
}
}
}
Throttle speichert die Argumente des letzten Aufrufs und richtet ein Intervall ein, um solange zu feuern, bis keine vergangenen Feuer mehr vorhanden sind.
Ähnlichkeiten. Sie haben beide eine Verzögerungszeit, und es erfolgt kein Feuer während der Verzögerung, insbesondere wenn es nur ein Feuer gibt. Beide aggregieren keine vergangenen Ereignisse, daher kann die Anzahl der Ereignisse von den tatsächlichen Feuern abweichen.
Unterschied. Die Verzögerung kann im Fall von Debounce bei wiederholten Ereignissen verlängert werden. Während die Verzögerung im Fall von Throttle fest ist. Insgesamt erhält man also mehr Feuer von Throttle als von Debounce.
Leicht zu merken. Debounce gruppiert Anrufe zu einem Bündel. Throttle hält Bündelanrufe innerhalb einer bestimmten Frequenz aufrecht.
Aktualisiert am 1-20-23
Throttle benötigt möglicherweise kein setInterval
, hier ist eine neue Version, die ich kürzlich geschrieben habe und sich auch um this
kümmert.
function throttle(fn, delay) {
let canFire = true
let queue = []
function pop() {
if (queue.length < 1) return
const [that, args] = queue.pop()
fn.apply(that, args)
canFire = false
setTimeout(() => {
canFire = true
pop()
}, delay)
}
function push() {
queue.push([this, arguments])
if (canFire) pop()
}
push.cancel = () => {
queue = []
}
return push
}
Aktualisiert am 11-09-23
Ich beginne zu glauben, dass Throttle ein Add-On auf Debounce ist. Lesen Sie dies https://windmaomao.medium.com/throttle-is-a-debounce-add-on-80d4a6027ad4.
function throttle(fn, delay) {
let h
let queue = []
function pop() {
if (queue.length < 1) return
if (!h) {
const [that, args] = queue.pop()
fn.apply(that, args)
h = setTimeout(() => {
h = null
pop()
}, delay)
}
}
return function push() {
queue.push([this, arguments])
pop()
}
}