@@ -36,7 +36,7 @@ export class Provider<T extends Name> {
36
36
constructor (
37
37
private readonly name : T ,
38
38
private readonly container : ComponentContainer
39
- ) { }
39
+ ) { }
40
40
41
41
/**
42
42
* @param identifier A provider can provide mulitple instances of a service
@@ -50,9 +50,14 @@ export class Provider<T extends Name> {
50
50
const deferred = new Deferred < NameServiceMapping [ T ] > ( ) ;
51
51
this . instancesDeferred . set ( normalizedIdentifier , deferred ) ;
52
52
// If the service instance is available, resolve the promise with it immediately
53
- const instance = this . getOrInitializeService ( normalizedIdentifier ) ;
54
- if ( instance ) {
55
- deferred . resolve ( instance ) ;
53
+ try {
54
+ const instance = this . getOrInitializeService ( normalizedIdentifier ) ;
55
+ if ( instance ) {
56
+ deferred . resolve ( instance ) ;
57
+ }
58
+ } catch ( e ) {
59
+ // when the instance factory throws an exception during get(), it should not cause
60
+ // an fatal error. We just return the unresolved promise in this case.
56
61
}
57
62
}
58
63
@@ -86,17 +91,24 @@ export class Provider<T extends Name> {
86
91
} ;
87
92
// if multipleInstances is not supported, use the default name
88
93
const normalizedIdentifier = this . normalizeInstanceIdentifier ( identifier ) ;
94
+ try {
95
+ const instance = this . getOrInitializeService ( normalizedIdentifier ) ;
89
96
90
- const instance = this . getOrInitializeService ( normalizedIdentifier ) ;
97
+ if ( ! instance ) {
98
+ if ( optional ) {
99
+ return null ;
100
+ }
101
+ throw Error ( `Service ${ this . name } is not available` ) ;
102
+ }
91
103
92
- if ( ! instance ) {
104
+ return instance ;
105
+ } catch ( e ) {
93
106
if ( optional ) {
94
107
return null ;
108
+ } else {
109
+ throw e ;
95
110
}
96
- throw Error ( `Service ${ this . name } is not available` ) ;
97
111
}
98
-
99
- return instance ;
100
112
}
101
113
102
114
setComponent ( component : Component < T > ) : void {
@@ -113,7 +125,14 @@ export class Provider<T extends Name> {
113
125
this . component = component ;
114
126
// if the service is eager, initialize the default instance
115
127
if ( isComponentEager ( component ) ) {
116
- this . getOrInitializeService ( DEFAULT_ENTRY_NAME ) ;
128
+ try {
129
+ this . getOrInitializeService ( DEFAULT_ENTRY_NAME ) ;
130
+ } catch ( e ) {
131
+ // when the instance factory for an eager Component throws an exception during the eager
132
+ // initialization, it should not cause an fatal error.
133
+ // TODO: Investigate if we need to make it configurable, because some component may want to cause
134
+ // a fatal error in this case?
135
+ }
117
136
}
118
137
119
138
// Create service instances for the pending promises and resolve them
@@ -127,10 +146,14 @@ export class Provider<T extends Name> {
127
146
instanceIdentifier
128
147
) ;
129
148
130
- // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
131
- const instance = this . getOrInitializeService ( normalizedIdentifier ) ! ;
132
-
133
- instanceDeferred . resolve ( instance ) ;
149
+ try {
150
+ // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
151
+ const instance = this . getOrInitializeService ( normalizedIdentifier ) ! ;
152
+ instanceDeferred . resolve ( instance ) ;
153
+ } catch ( e ) {
154
+ // when the instance factory throws an exception, it should not cause
155
+ // an fatal error. We just leave the promise unresolved.
156
+ }
134
157
}
135
158
}
136
159
0 commit comments