svp revised this gist . Go to revision
1 file changed, 83 insertions
local-storage.service.ts(file created)
@@ -0,0 +1,83 @@ | |||
1 | + | import { Injectable } from '@angular/core'; | |
2 | + | import { fromEvent, merge, Observable, Subject } from 'rxjs'; | |
3 | + | import { filter, map, startWith } from 'rxjs/operators'; | |
4 | + | ||
5 | + | export interface LocalStorageObject { | |
6 | + | name: string; | |
7 | + | value: string | null; | |
8 | + | } | |
9 | + | ||
10 | + | const deserializeValue = <T>(value: string): T => { | |
11 | + | try { | |
12 | + | return JSON.parse(value); | |
13 | + | } catch { | |
14 | + | return value as unknown as T; | |
15 | + | } | |
16 | + | }; | |
17 | + | ||
18 | + | @Injectable({ | |
19 | + | providedIn: 'root', | |
20 | + | }) | |
21 | + | export class LocalStorageService { | |
22 | + | private _storage = window.localStorage; | |
23 | + | ||
24 | + | private _storageUpdateNotifier$ = new Subject<LocalStorageObject | null>(); | |
25 | + | ||
26 | + | storageUpdates$ = this._storageUpdateNotifier$.asObservable(); | |
27 | + | ||
28 | + | initLocalStorage(storageObjs: LocalStorageObject[]): void { | |
29 | + | if (this._isLocalStorageEnabled()) { | |
30 | + | storageObjs.forEach(({ name, value }) => { | |
31 | + | this._storage.setItem(name, value); | |
32 | + | }); | |
33 | + | } | |
34 | + | } | |
35 | + | ||
36 | + | setItem(key: string, value: string): void { | |
37 | + | this._storage.setItem(key, value); | |
38 | + | this._storageUpdateNotifier$.next({ name: key, value }); | |
39 | + | } | |
40 | + | ||
41 | + | getItem(key: string): any { | |
42 | + | const retrieved = this._storage.getItem(key); | |
43 | + | try { | |
44 | + | return deserializeValue(retrieved); | |
45 | + | } catch { | |
46 | + | return retrieved; | |
47 | + | } | |
48 | + | } | |
49 | + | ||
50 | + | removeItem(key: string): void { | |
51 | + | this._storage.removeItem(key); | |
52 | + | this._storageUpdateNotifier$.next({ name: key, value: null }); | |
53 | + | } | |
54 | + | ||
55 | + | clear(): void { | |
56 | + | this._storage.clear(); | |
57 | + | this._storageUpdateNotifier$.next(null); | |
58 | + | } | |
59 | + | ||
60 | + | getUpdatesForKey<T>(key: string): Observable<T> { | |
61 | + | return merge( | |
62 | + | fromEvent(window, 'storage').pipe( | |
63 | + | filter((event: StorageEvent) => event.key === key), | |
64 | + | map(data => deserializeValue(data.newValue)) | |
65 | + | ), | |
66 | + | this.storageUpdates$.pipe( | |
67 | + | filter(update => update.name === key), | |
68 | + | map(update => deserializeValue(update.value)) | |
69 | + | ) | |
70 | + | ).pipe(startWith(this.getItem(key) || false)); | |
71 | + | } | |
72 | + | ||
73 | + | private _isLocalStorageEnabled(): boolean { | |
74 | + | try { | |
75 | + | const key = `__storage__test`; | |
76 | + | this._storage.setItem(key, null); | |
77 | + | this._storage.removeItem(key); | |
78 | + | return true; | |
79 | + | } catch (e) { | |
80 | + | return false; | |
81 | + | } | |
82 | + | } | |
83 | + | } |
Newer
Older