@@ -44,36 +44,48 @@ export function remote(urls: string[] | string, options: IOptions): es.ThroughSt
44
44
} ) ) ;
45
45
}
46
46
47
- async function fetchWithRetry ( url : string , options : IOptions , retries = 10 , retryDelay = 250 ) : Promise < VinylFile > {
47
+ async function fetchWithRetry ( url : string , options : IOptions , retries = 10 , retryDelay = 1000 ) : Promise < VinylFile > {
48
48
try {
49
49
let startTime = 0 ;
50
50
if ( options . verbose ) {
51
51
log ( `Start fetching ${ ansiColors . magenta ( url ) } ${ retries !== 10 ? `(${ 10 - retries } retry}` : '' } ` ) ;
52
52
startTime = new Date ( ) . getTime ( ) ;
53
53
}
54
- const response = await fetch ( url , options . fetchOptions ) ;
55
- if ( options . verbose ) {
56
- log ( `Fetch completed: Status ${ response . status } . Took ${ ansiColors . magenta ( `${ new Date ( ) . getTime ( ) - startTime } ms` ) } ` ) ;
57
- }
58
- if ( response . ok && ( response . status >= 200 && response . status < 300 ) ) {
59
- // request must be piped out once created, or we'll get this error: "You cannot pipe after data has been emitted from the response."
60
- const contents = options . buffer ? await response . buffer ( ) : response . body . pipe ( through2 ( ) ) ;
61
- return new VinylFile ( {
62
- cwd : '/' ,
63
- base : options . base ,
64
- path : url ,
65
- contents
54
+ const controller = new AbortController ( ) ;
55
+ const timeout = setTimeout ( ( ) => controller . abort ( ) , 30 * 1000 ) ;
56
+ try {
57
+ const response = await fetch ( url , {
58
+ ...options . fetchOptions ,
59
+ signal : controller . signal as any /* Typings issue with lib.dom.d.ts */
66
60
} ) ;
61
+ if ( options . verbose ) {
62
+ log ( `Fetch completed: Status ${ response . status } . Took ${ ansiColors . magenta ( `${ new Date ( ) . getTime ( ) - startTime } ms` ) } ` ) ;
63
+ }
64
+ if ( response . ok && ( response . status >= 200 && response . status < 300 ) ) {
65
+ // request must be piped out once created, or we'll get this error: "You cannot pipe after data has been emitted from the response."
66
+ const contents = options . buffer ? await response . buffer ( ) : response . body . pipe ( through2 ( ) ) ;
67
+ if ( options . buffer && options . verbose ) {
68
+ log ( `Fetched response body buffer: ${ ansiColors . magenta ( `${ ( contents as Buffer ) . byteLength } bytes` ) } ` ) ;
69
+ }
70
+ return new VinylFile ( {
71
+ cwd : '/' ,
72
+ base : options . base ,
73
+ path : url ,
74
+ contents
75
+ } ) ;
76
+ }
77
+ throw new Error ( `Request ${ ansiColors . magenta ( url ) } failed with status code: ${ response . status } ` ) ;
78
+ } finally {
79
+ clearTimeout ( timeout ) ;
67
80
}
68
- throw new Error ( `Request ${ ansiColors . magenta ( url ) } failed with status code: ${ response . status } ` ) ;
69
81
} catch ( e ) {
70
- if ( retries > 0 ) {
71
- await new Promise ( c => setTimeout ( c , retryDelay ) ) ;
72
- return fetchWithRetry ( url , options , retries - 1 , retryDelay * 2 ) ;
73
- }
74
82
if ( options . verbose ) {
75
83
log ( `Fetching ${ ansiColors . cyan ( url ) } failed: ${ e } ` ) ;
76
84
}
85
+ if ( retries > 0 ) {
86
+ await new Promise ( resolve => setTimeout ( resolve , retryDelay ) ) ;
87
+ return fetchWithRetry ( url , options , retries - 1 , retryDelay ) ;
88
+ }
77
89
throw e ;
78
90
}
79
91
}
0 commit comments