Last active
February 4, 2022 17:46
-
-
Save mattkenefick/6ae56fc742fbffea7107fef7c041ac21 to your computer and use it in GitHub Desktop.
debounce.ts
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
/** | |
* Debounce (Inclusive) | |
* | |
* Prevents a function from being fired too often by determining | |
* a difference in time from the last time in which it was fired. | |
* | |
* Applies inclusive techniques to execute functions one last time. | |
* | |
* @author Matt Kenefick <polymermallard.com> | |
* @see https://medium.com/@mattkenefick/debouncing-in-typescript-d5edddf39cdc | |
*/ | |
export default class Debounce { | |
/** | |
* Statically call a debounced method and infer its categorization | |
* | |
* @return void | |
*/ | |
public static exec(reference: symbol, callable: () => void, args: any[] = [], timeout: number = 1000): void { | |
if (!this.instances[reference]) { | |
const instance = new Debounce(callable, timeout); | |
this.instances[reference] = instance.run; | |
} | |
this.instances[reference](...args); | |
} | |
/** | |
* Static references to debouncers generated by the `exec` call | |
* | |
* @type [symbol, any] | |
*/ | |
private static instances: any = {}; | |
/** | |
* Debounced function | |
* | |
* @type function | |
*/ | |
public callback: () => void; | |
/** | |
* Time in between triggers | |
* | |
* @type number | |
*/ | |
public threshold: number; | |
/** | |
* Last time this function was triggered | |
* | |
* @type number | |
*/ | |
private lastTrigger: number = 0; | |
/** | |
* Timeout for calling future events | |
* | |
* @type number | |
*/ | |
private timeout: number = 0; | |
/** | |
* @param function callback | |
* @param number threshold | |
* @return function | |
*/ | |
public constructor(callback: () => void, threshold: number = 200) { | |
this.callback = callback; | |
this.threshold = threshold; | |
// Don't execute on first pass; only after threshold waits | |
// Disable this if you want immediate execution as well as inclusive | |
this.lastTrigger = Date.now(); | |
this.run = this.run.bind(this); | |
} | |
/** | |
* Executable function | |
* | |
* @return void | |
*/ | |
public run(): void { | |
const now: number = Date.now(); | |
const diff: number = now - this.lastTrigger; | |
// Execute Immediately | |
if (diff > this.threshold) { | |
this.lastTrigger = now; | |
this.callback(); | |
} | |
// Cancel future event, if exists | |
if (this.timeout !== 0) { | |
clearTimeout(this.timeout); | |
this.timeout = 0; | |
} | |
// Create future event | |
this.timeout = setTimeout(this.callback, this.threshold); | |
} | |
} |
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
export default class ViewFormField extends ViewBase { | |
/** | |
* @param Event e | |
* @return void | |
*/ | |
protected Handle_OnInput(e: Event): void { | |
const input: HTMLInputElement = e.currentTarget as HTMLInputElement; | |
const name: string = input.name as string; | |
const value: string = input.value as string; | |
// Find model in collection | |
const model = this.collection.findWhere({ key: name }); | |
// Set `value` on model | |
model && model.set({ value }); | |
// Save to server every 1s | |
// You can pass any symbol, but this example assumes your classes all have a unique symbol | |
Debounce.exec(this.symbol, () => model.save()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment