Last active
September 18, 2017 18:07
-
-
Save PatrickJS/1852053c7e629c9ea3720415c381ecd3 to your computer and use it in GitHub Desktop.
Universal 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
// Something like this. I haven't tested this file | |
@Injectable() | |
export class ApiService { | |
constructor(public _http: Http, public _cache: Cache) { | |
} | |
// whatever domain/feature method name | |
getModel(url) { | |
// you want to return the cache if there is a response in it. This would cache the first response so if your API isn't idempotent you probably want to remove the item from the cache after you use it. LRU of 1 | |
let key = url; | |
if (this._cache.has(key)) { | |
return Observable.of(this._cache.get(key)); | |
} | |
// you probably shouldn't .share() and you should write the correct logic | |
return this._http.get(url) | |
.map(res => res.json()) | |
.do(json => { | |
this._cache.set(key, json); | |
}) | |
.share(); | |
} | |
} |
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
// Something like this. I haven't tested this file | |
@Component({ | |
selector: 'app', | |
template: ` | |
<ul> | |
<li *ngFor="let item of collection"> | |
{{ item | json }} | |
</li> | |
</ul> | |
` | |
}) | |
export class AppComponent { | |
collection: any; | |
constructor(public api: ApiService) { | |
this.api.getModel('/data.json').subscribe((json) => this.collection = json) | |
} | |
} |
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
// Something like this. I haven't tested this file | |
@NgModule({ | |
declarations: [ | |
AppComponent | |
], | |
bootstrap: [ | |
AppComponent | |
], | |
imports: [ UniversalModule ], | |
providers: [ ApiService, Cache ] | |
}) | |
export class AppModule { | |
constructor(public cache: Cache) { | |
} | |
// we need to use the arrow function here to bind the context as this is a gotcha in Universal for now until it's fixed | |
universalDoDehydrate = (universalCache) => { | |
let self = this; | |
universalCache['Cache'] = JSON.stringify(self.cache.dehydrate()); | |
} | |
universalAfterDehydrate = () => { | |
let self = this; | |
self.cache.clear(); | |
} | |
} |
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
// Something like this. I haven't tested this file | |
import { isBrowser } from 'angular2-universal'; // might have problems with AoT so use DI to determine if browser for now | |
import { Injectable } from '@angular/core'; | |
function rehydrateCache(defaultValue) { | |
if (!isBrowser) { return defaultValue; } | |
const win: any = window; | |
if (win['UNIVERSAL_CACHE'] && win['UNIVERSAL_CACHE']['Cache']) { | |
let serverCache = defaultValue; | |
try { | |
serverCache = JSON.parse(win['UNIVERSAL_CACHE']['Cache']); | |
if (typeof serverCache !== typeof defaultValue) { | |
serverCache = defaultValue; | |
} | |
} catch (e) { | |
serverCache = defaultValue; | |
} | |
return serverCache; | |
} | |
return defaultValue; | |
} | |
@Injectable() | |
export class Cache { | |
_cache = {}; // use LRU on the server | |
constructor() { | |
if (isBrowser) { | |
let serverCache = rehydrateCache(this._cache); | |
this.rehydrate(serverCache); | |
} | |
} | |
has(key: string): boolean { | |
return this._cache.hasOwnProperty(key); | |
} | |
set(key: string, value: any): void { | |
this._cache[key] = value; | |
} | |
get(key: string): any { | |
return this._cache[key]; | |
} | |
clear(): void { | |
Object.keys(this._cache).forEach((key) => { | |
delete this._cache[key]; | |
}); | |
} | |
dehydrate() { | |
let json = {}; | |
Object.keys(this._cache).forEach((key: string) => { | |
json[key] = this._cache[key]; | |
}); | |
return json; | |
} | |
rehydrate(json) { | |
Object.keys(json).forEach((key: string) => { | |
this._cache[key] = json[key]; | |
}); | |
} | |
toJSON() { | |
return this.dehydrate(); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment