@@ -2,116 +2,78 @@ import { OptimizelyDatafile } from './OptimizelySDKWrapper'
2
2
import { UserAttributes } from '@optimizely/optimizely-sdk'
3
3
import { UserId } from './UserIdLoaders'
4
4
5
- import {
6
- ResourceEmitter ,
7
- ResourceStream ,
8
- SingleResourceStream ,
9
- ResourceLoader ,
10
- CombinedResourceStream ,
11
- } from './ResourceStream'
12
-
13
- interface Resource < K > {
14
- getValue ( ) : K | undefined
15
- hasValue ( ) : boolean
16
- isReady ( ) : boolean
17
- hasFailed ( ) : boolean
18
- getMetadata ( ) : ResourceEmitter . DataMessage . Metadata | undefined
19
- getFailureReason ( ) : string
5
+ export interface ResourceLoader < K > {
6
+ load : ( ) => K | Promise < K >
20
7
}
21
8
22
- type ResourceLoaderState < K > = {
23
- resource : K | undefined
24
- metadata : ResourceEmitter . DataMessage . Metadata | undefined
25
- isReady : boolean
26
- failed : boolean
27
- failureReason : string
28
- }
29
-
30
- class BaseResource < K > implements Resource < K > {
31
- public stream : ResourceStream < K >
32
- protected state : ResourceLoaderState < K >
9
+ class Resource < K > {
10
+ private loader : ResourceLoader < K >
33
11
34
- constructor ( loader : ResourceLoader < K > ) {
35
- this . state = {
36
- resource : undefined ,
37
- metadata : undefined ,
38
- isReady : false ,
39
- failed : false ,
40
- failureReason : '' ,
41
- }
12
+ private _value ?: K
42
13
43
- this . stream = new SingleResourceStream ( loader )
44
- this . stream . subscribe ( {
45
- data : msg => {
46
- this . state . resource = msg . resource
47
- this . state . metadata = msg . metadata
48
- } ,
49
- ready : ( ) => {
50
- this . state . isReady = true
51
- } ,
52
- error : msg => {
53
- this . state . failed = true
54
- this . state . failureReason = msg . reason
55
- } ,
56
- } )
57
- }
14
+ private _hasLoaded : boolean
58
15
59
- getValue ( ) : K | undefined {
60
- return this . state . resource
61
- }
16
+ public readonly promise : Promise < K >
62
17
63
- hasValue ( ) : boolean {
64
- return this . getValue ( ) !== void 0
18
+ public get value ( ) : K | undefined {
19
+ return this . _value
65
20
}
66
21
67
- isReady ( ) : boolean {
68
- return this . state . isReady
22
+ public get hasLoaded ( ) : boolean {
23
+ return this . _hasLoaded
69
24
}
70
25
71
- hasFailed ( ) : boolean {
72
- return this . state . failed
73
- throw new Error ( 'Method not implemented.' )
26
+ constructor ( loader : ResourceLoader < K > ) {
27
+ this . loader = loader ;
28
+ this . _hasLoaded = false ;
29
+ this . promise = this . load ( ) ;
74
30
}
75
31
76
- getMetadata ( ) : ResourceEmitter . DataMessage . Metadata | undefined {
77
- return this . state . metadata
32
+ private updateStateFromLoadResult ( value : K ) {
33
+ this . _value = value ;
34
+ this . _hasLoaded = true ;
78
35
}
79
36
80
- getFailureReason ( ) : string {
81
- return this . state . failureReason
37
+ private load ( ) : Promise < K > {
38
+ const maybeValue = this . loader . load ( )
39
+ // TODO: test does this work with polyfilled promise?
40
+ if ( maybeValue instanceof Promise ) {
41
+ return maybeValue . then ( value => {
42
+ this . updateStateFromLoadResult ( value ) ;
43
+ return value
44
+ } )
45
+ }
46
+ this . updateStateFromLoadResult ( maybeValue ) ;
47
+ return Promise . resolve ( maybeValue ) ;
82
48
}
83
49
}
84
50
85
- export class ResourceManager {
86
- protected resourceKeys = [ 'datafile' , 'attributes' , 'userId' ]
51
+ type OptimizelyResource = OptimizelyDatafile | UserAttributes | UserId
87
52
88
- public datafile : BaseResource < OptimizelyDatafile >
89
- public attributes : BaseResource < UserAttributes >
90
- public userId : BaseResource < UserId >
53
+ export class ResourceManager {
54
+ public datafile : Resource < OptimizelyDatafile >
55
+ public attributes : Resource < UserAttributes >
56
+ public userId : Resource < UserId >
91
57
92
- public stream : ResourceStream < any >
58
+ private resources : Resource < OptimizelyResource > [ ]
93
59
94
60
constructor ( loaders : {
95
61
datafile : ResourceLoader < OptimizelyDatafile >
96
62
attributes : ResourceLoader < UserAttributes >
97
63
userId : ResourceLoader < UserId >
98
64
} ) {
99
- this . datafile = new BaseResource ( loaders . datafile )
100
- this . attributes = new BaseResource ( loaders . attributes )
101
- this . userId = new BaseResource ( loaders . userId )
102
-
103
- this . stream = new CombinedResourceStream ( [ this . datafile . stream , this . attributes . stream , this . userId . stream ] )
104
- }
65
+ this . datafile = new Resource ( loaders . datafile )
66
+ this . attributes = new Resource ( loaders . attributes )
67
+ this . userId = new Resource ( loaders . userId )
105
68
106
- allResourcesHaveValues ( ) : boolean {
107
- return this . everyResource ( resource => resource . hasValue ( ) )
69
+ this . resources = [ this . datafile , this . attributes , this . userId ] ;
108
70
}
109
71
110
- allResourcesReady ( ) : boolean {
111
- return this . everyResource ( resource => resource . isReady ( ) )
72
+ public allResourcesLoaded ( ) : boolean {
73
+ return this . resources . every ( resource => resource . hasLoaded ) ;
112
74
}
113
75
114
- private everyResource ( fn : ( resource : Resource < any > ) => boolean ) : boolean {
115
- return this . resourceKeys . every ( key => fn ( this [ key ] ) )
76
+ public allResourcePromises ( ) : Promise < OptimizelyResource [ ] > {
77
+ return Promise . all ( [ ... this . resources . map ( resource => resource . promise ) ] )
116
78
}
117
79
}
0 commit comments