@@ -34,7 +34,10 @@ type Props = {
34
34
35
35
export class WidgetManagerComponent extends React . Component < Props > {
36
36
private readonly widgetManager : WidgetManager ;
37
- private readonly widgetSourceRequests = new Map < string , Deferred < void > > ( ) ;
37
+ private readonly widgetSourceRequests = new Map <
38
+ string ,
39
+ { deferred : Deferred < void > ; timer : NodeJS . Timeout | number | undefined }
40
+ > ( ) ;
38
41
private timedoutWaitingForWidgetsToGetLoaded ?: boolean ;
39
42
private widgetsCanLoadFromCDN : boolean = false ;
40
43
private readonly loaderSettings = {
@@ -107,12 +110,19 @@ export class WidgetManagerComponent extends React.Component<Props> {
107
110
sources . forEach ( ( source ) => {
108
111
// We have fetched the script sources for all of these modules.
109
112
// In some cases we might not have the source, meaning we don't have it or couldn't find it.
110
- let deferred = this . widgetSourceRequests . get ( source . moduleName ) ;
111
- if ( ! deferred ) {
112
- deferred = createDeferred ( ) ;
113
- this . widgetSourceRequests . set ( source . moduleName , deferred ) ;
113
+ let request = this . widgetSourceRequests . get ( source . moduleName ) ;
114
+ if ( ! request ) {
115
+ request = {
116
+ deferred : createDeferred ( ) ,
117
+ timer : undefined
118
+ } ;
119
+ this . widgetSourceRequests . set ( source . moduleName , request ) ;
120
+ }
121
+ request . deferred . resolve ( ) ;
122
+ if ( request . timer !== undefined ) {
123
+ // tslint:disable-next-line: no-any
124
+ clearTimeout ( request . timer as any ) ; // This is to make this work on Node and Browser
114
125
}
115
- deferred . resolve ( ) ;
116
126
} ) ;
117
127
}
118
128
private registerScriptSourceInRequirejs ( source ?: WidgetScriptSource ) {
@@ -180,10 +190,12 @@ export class WidgetManagerComponent extends React.Component<Props> {
180
190
private loadWidgetScript ( moduleName : string , moduleVersion : string ) : Promise < void > {
181
191
// tslint:disable-next-line: no-console
182
192
console . log ( `Fetch IPyWidget source for ${ moduleName } ` ) ;
183
- let deferred = this . widgetSourceRequests . get ( moduleName ) ;
184
- if ( ! deferred ) {
185
- deferred = createDeferred < void > ( ) ;
186
- this . widgetSourceRequests . set ( moduleName , deferred ) ;
193
+ let request = this . widgetSourceRequests . get ( moduleName ) ;
194
+ if ( ! request ) {
195
+ request = {
196
+ deferred : createDeferred < void > ( ) ,
197
+ timer : undefined
198
+ } ;
187
199
188
200
// If we timeout, then resolve this promise.
189
201
// We don't want the calling code to unnecessary wait for too long.
@@ -193,18 +205,26 @@ export class WidgetManagerComponent extends React.Component<Props> {
193
205
// Possible user has ignored some UI prompt and things are now in a state of limbo.
194
206
// This way thigns will fall over sooner due to missing widget sources.
195
207
const timeoutTime = this . timedoutWaitingForWidgetsToGetLoaded
196
- ? 10_000
208
+ ? 5_000
197
209
: this . loaderSettings . timeoutWaitingForScriptToLoad ;
198
210
199
- setTimeout ( ( ) => {
200
- // tslint:disable-next-line: no-console
201
- console . error ( `Timeout waiting to get widget source for ${ moduleName } , ${ moduleVersion } ` ) ;
202
- this . handleLoadError ( '<class>' , moduleName , moduleVersion , new Error ( 'Timeout' ) , true ) . ignoreErrors ( ) ;
203
- if ( deferred ) {
204
- deferred . resolve ( ) ;
211
+ request . timer = setTimeout ( ( ) => {
212
+ if ( request && ! request . deferred . resolved ) {
213
+ // tslint:disable-next-line: no-console
214
+ console . error ( `Timeout waiting to get widget source for ${ moduleName } , ${ moduleVersion } ` ) ;
215
+ this . handleLoadError (
216
+ '<class>' ,
217
+ moduleName ,
218
+ moduleVersion ,
219
+ new Error ( `Timeout getting source for ${ moduleName } :${ moduleVersion } ` ) ,
220
+ true
221
+ ) . ignoreErrors ( ) ;
222
+ request . deferred . resolve ( ) ;
223
+ this . timedoutWaitingForWidgetsToGetLoaded = true ;
205
224
}
206
- this . timedoutWaitingForWidgetsToGetLoaded = true ;
207
225
} , timeoutTime ) ;
226
+
227
+ this . widgetSourceRequests . set ( moduleName , request ) ;
208
228
}
209
229
// Whether we have the scripts or not, send message to extension.
210
230
// Useful telemetry and also we know it was explicity requestd by ipywidgest.
@@ -213,7 +233,7 @@ export class WidgetManagerComponent extends React.Component<Props> {
213
233
{ moduleName, moduleVersion }
214
234
) ;
215
235
216
- return deferred . promise . catch ( ( ex ) =>
236
+ return request . deferred . promise . catch ( ( ex ) =>
217
237
// tslint:disable-next-line: no-console
218
238
console . error ( `Failed to load Widget Script from Extension for for ${ moduleName } , ${ moduleVersion } ` , ex )
219
239
) ;
0 commit comments