Created
May 9, 2022 14:39
-
-
Save jabney/4982a1d622eb99645f239adc55483721 to your computer and use it in GitHub Desktop.
An example of class composition with a timed value cache
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
interface IValueCache<T> { | |
get: () => T; | |
invalidate: () => void; | |
} | |
/** | |
* A simple cache that invalidates based on a timer. Every access of | |
* the value will refresh the timer. | |
* | |
* Even this simple class can be broken up into useful pieces and then | |
* composited into a new timer cache. | |
*/ | |
class SimpleTimerCache<T> implements IValueCache<T> { | |
private value: T | null = null; | |
private timer = -1; | |
constructor(private readonly ms: number, private readonly cacheFn: () => T) {} | |
invalidate = () => void (this.value = null); | |
get = () => { | |
if (this.value == null) this.value = this.cacheFn(); | |
if (this.ms >= 0) { | |
clearTimeout(this.timer); | |
this.timer = setTimeout(this.invalidate, this.ms); | |
} | |
return this.value; | |
}; | |
} | |
/** | |
* Basic cache will store a value until it's invalidated. | |
*/ | |
class BasicCache<T> implements IValueCache<T> { | |
private value: T | null = null; | |
constructor(private readonly refresh: () => T) {} | |
invalidate = () => void (this.value = null); | |
get = () => { | |
if (this.value == null) { | |
this.value = this.refresh(); | |
} | |
return this.value; | |
}; | |
} | |
/** | |
* Basic timer can be started, stopped, and reset. | |
*/ | |
class BasicTimer { | |
private id = -1; | |
constructor(private readonly ms: number, private readonly action: () => void) {} | |
start = () => void (this.id = setTimeout(this.action, this.ms)); | |
stop = () => void clearTimeout(this.id); | |
reset = () => void (this.stop(), this.start()); | |
} | |
/** | |
* This timer cache is a composite of the basic cache and the basic timer. | |
*/ | |
class TimerCache<T> implements IValueCache<T> { | |
private cache: BasicCache<T>; | |
private timer: BasicTimer; | |
constructor(ms: number, refresh: () => T) { | |
this.cache = new BasicCache<T>(refresh); | |
this.timer = new BasicTimer(ms, this.cache.invalidate); | |
} | |
get = () => { | |
this.timer.reset(); | |
return this.cache.get(); | |
}; | |
invalidate = () => this.cache.invalidate(); | |
} | |
(() => { | |
const cache = new TimerCache(1000, () => (console.log("cache refreshed"), 1)); | |
cache.get(); | |
setTimeout(cache.get, 500); | |
setTimeout(cache.get, 1000); | |
setTimeout(cache.get, 1500); | |
setTimeout(cache.get, 2000); | |
setTimeout(cache.get, 2500); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment