-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: start working on new debouncer class
- Loading branch information
Showing
2 changed files
with
75 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { NanoEmitter } from "./NanoEmitter.js"; | ||
|
||
/** | ||
* The type of edge to use for the debouncer - [see this issue for an explanation and diagram.](https://github.com/Sv443-Network/UserUtils/issues/46) | ||
* - `queuedImmediate` | ||
* (Default & recommended) calls the listeners at the very first call ("rising" edge) and queues the latest call until the timeout expires | ||
* Pros: reacts immediately, doesn't delete the last call | ||
* Cons: All subsequent calls are delayed by the timeout duration | ||
* - `queuedIdle` | ||
* Queues all calls until there are no more calls in the given timeout duration ("falling" edge), and only then executes the very last call | ||
* Pros: Always makes sure the last call is executed | ||
* Cons: Calls are always delayed by the timeout duration, first call is likely to be discarded, calls could get stuck in the queue indefinitely if the calls are made faster than the timeout | ||
* - `discardingImmediate` | ||
* Calls the listeners at the very last call ("falling" edge), then allows another through after the timeout expired, without queuing any calls | ||
* Pros: Always acts upon calls immediately without delaying them in a queue, interval is somewhat predictable with events that fire often | ||
* Cons: Likely to discard the latest call leading to a loss of data | ||
*/ | ||
export type DebouncerEdgeType = "queuedImmediate" | "queuedIdle" | "discardingImmediate"; | ||
|
||
/** | ||
* A debouncer that calls all listeners after a specified timeout, discarding all calls in-between. | ||
* It is very useful for event listeners that fire quickly, like `input` or `mousemove`, to prevent the listeners from being called too often and hogging resources. | ||
* | ||
* The exact behavior can be customized with the `edge` parameter. | ||
*/ | ||
export class Debouncer<TArgs> extends NanoEmitter<{ | ||
call: (...args: TArgs[]) => void; | ||
change: (timeout: number, edge: DebouncerEdgeType) => void; | ||
}> { | ||
/** All registered listener functions and the time they were attached */ | ||
protected listeners: [time: number, fn: (...args: TArgs[]) => void | unknown][] = []; | ||
/** The latest call that was queued */ | ||
protected queuedCall: typeof this.listeners[number] | undefined = undefined; | ||
|
||
constructor(protected timeout = 200, protected edge: DebouncerEdgeType = "queuedImmediate") { | ||
super(); | ||
} | ||
|
||
/** Sets the timeout for the debouncer */ | ||
public setTimeout(timeout: number) { | ||
this.emit("change", this.timeout = timeout, this.edge); | ||
} | ||
|
||
/** Sets the edge type for the debouncer */ | ||
public setEdge(edge: DebouncerEdgeType) { | ||
this.emit("change", this.timeout, this.edge = edge); | ||
} | ||
|
||
/** Adds a listener function that will be called on timeout */ | ||
public addListener(fn: (...args: TArgs[]) => void | unknown) { | ||
return this.listeners.push([Date.now(), fn]); | ||
} | ||
|
||
/** Removes the listener with the specified function reference */ | ||
public removeListener(fn: (...args: TArgs[]) => void | unknown) { | ||
const idx = this.listeners.findIndex((l) => l[1] === fn); | ||
idx !== -1 && this.listeners.splice(idx, 1); | ||
} | ||
|
||
/** Use this to call the debouncer with the specified arguments that will be passed to all listener functions registered with {@linkcode addListener()} */ | ||
public call(...args: TArgs[]) { | ||
void ["TODO:", args]; | ||
} | ||
} | ||
|
||
export function debounce< | ||
TFunc extends (...args: TArgs[]) => void | unknown, | ||
TArgs, | ||
> (fn: TFunc, timeout = 200, edge: DebouncerEdgeType = "queuedImmediate"): (...args: TArgs[]) => void { | ||
Check failure on line 69 in lib/Debouncer.ts
|
||
const debouncer = new Debouncer<TArgs>(timeout, edge); | ||
debouncer.addListener(fn); | ||
|
||
// TODO: | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters