-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPersistor.ts
79 lines (65 loc) · 2.45 KB
/
Persistor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { print, printError } from '../utils/utils';
/**
* This class is used to manage the state of some specific information being saved to the local device disk.
* It keeps track of the last saved state, the current state, and whether a load or save operation is in progress.
* It also provides methods to check if the state has changed, if it's the first invocation, and to process save and load operations.
*/
export class Persistor<T> {
lastSaved: T | null = null;
current: T | null = null;
isBusy: boolean = false;
/** Returns True if the state has changed, false otherwise. */
hasChanged() {
return this.lastSaved !== this.current;
}
/** Returns true if the state has changed and a load/save operation is not in progress. */
hasChangedAndIsNotBusy() {
return this.hasChanged() && !this.isBusy;
}
/** Returns true only the first time this method is called. */
isFirstInvocation() {
return (this.lastSaved == null) && !this.isBusy;
}
/**
* Processes a save operation.
* If the state has changed and a save operation is not in progress, it updates the last saved state to the
* current state, sets the isBusy flag to true, and executes the save function.
*
* An eventual save error will be thrown to the caller.
*
* @param {() => Promise<void>} saveFunction - The function that saves the state.
*/
processSave(saveFunction: (current: T, lastSaved: T | null) => Promise<void>) {
if (this.hasChangedAndIsNotBusy()) {
this.isBusy = true;
(async () => {
try {
if (this.current != null) {
await saveFunction(this.current, this.lastSaved);
}
// Note: Save error will be caught by StorageManager.localSavePortfolio().
} finally {
this.lastSaved = this.current;
this.isBusy = false;
}
})();
}
}
async loadIt(loadFunction: () => Promise<T>, name: String) {
try {
this.isBusy = true;
print(`Loading ${name}...`);
let loaded = await loadFunction();
this.lastSaved = loaded;
this.current = loaded;
this.isBusy = false;
} catch (error) {
// Should instead handle the error appropriately. If the local information
// is corrupted, delete the local information and recreate it. If the
// saved info is versioned, and the version is old, upgrade it.
printError(`Failed to load ${name}`, error);
} finally {
this.isBusy = false;
}
}
}