2
2
'use strict'
3
3
4
4
const fetch = require ( 'node-fetch' )
5
- const merge = require ( 'merge-options' )
5
+ const merge = require ( 'merge-options' ) . bind ( { ignoreUndefined : true } )
6
6
const { URL , URLSearchParams } = require ( 'iso-url' )
7
7
const TextDecoder = require ( './text-encoder' )
8
8
const AbortController = require ( 'abort-controller' )
9
+ const anySignal = require ( 'any-signal' )
9
10
10
11
const Request = fetch . Request
11
12
const Headers = fetch . Headers
@@ -32,24 +33,32 @@ const timeout = (promise, ms, abortController) => {
32
33
33
34
const start = Date . now ( )
34
35
36
+ const timedOut = ( ) => {
37
+ const time = Date . now ( ) - start
38
+
39
+ return time >= ms
40
+ }
41
+
35
42
return new Promise ( ( resolve , reject ) => {
43
+ const timeoutID = setTimeout ( ( ) => {
44
+ if ( timedOut ( ) ) {
45
+ reject ( new TimeoutError ( ) )
46
+ abortController . abort ( )
47
+ }
48
+ } , ms )
49
+
36
50
const after = ( next ) => {
37
51
return ( res ) => {
38
52
clearTimeout ( timeoutID )
39
- const time = Date . now ( ) - start
40
53
41
- if ( time >= ms ) {
42
- abortController . abort ( )
54
+ if ( timedOut ( ) ) {
43
55
reject ( new TimeoutError ( ) )
44
56
return
45
57
}
46
58
47
- if ( next ) {
48
- next ( res )
49
- }
59
+ next ( res )
50
60
}
51
61
}
52
- const timeoutID = setTimeout ( after ( ) , ms )
53
62
54
63
promise
55
64
. then ( after ( resolve ) , after ( reject ) )
@@ -88,18 +97,6 @@ class HTTP {
88
97
constructor ( options = { } ) {
89
98
/** @type {APIOptions } */
90
99
this . opts = merge ( defaults , options )
91
- this . opts . headers = new Headers ( options . headers )
92
-
93
- // connect internal abort to external
94
- this . abortController = new AbortController ( )
95
-
96
- if ( this . opts . signal ) {
97
- this . opts . signal . addEventListener ( 'abort' , ( ) => {
98
- this . abortController . abort ( )
99
- } )
100
- }
101
-
102
- this . opts . signal = this . abortController . signal
103
100
}
104
101
105
102
/**
@@ -144,13 +141,14 @@ class HTTP {
144
141
opts . headers . set ( 'content-type' , 'application/json' )
145
142
}
146
143
144
+ const abortController = new AbortController ( )
145
+ const signal = anySignal ( [ abortController . signal , opts . signal ] )
146
+
147
147
const response = await timeout ( fetch ( url , {
148
148
...opts ,
149
-
150
- // node-fetch implements it's own timeout in an addition to the spec so do not
151
- // pass the timeout value on, otherwise there are two sources of timeout errors
149
+ signal,
152
150
timeout : undefined
153
- } ) , opts . timeout , this . abortController )
151
+ } ) , opts . timeout , abortController )
154
152
155
153
if ( ! response . ok && opts . throwHttpErrors ) {
156
154
if ( opts . handleError ) {
@@ -188,7 +186,10 @@ class HTTP {
188
186
* @returns {Promise<Response> }
189
187
*/
190
188
post ( resource , options = { } ) {
191
- return this . fetch ( resource , merge ( this . opts , options , { method : 'POST' } ) )
189
+ return this . fetch ( resource , {
190
+ ...options ,
191
+ method : 'POST'
192
+ } )
192
193
}
193
194
194
195
/**
@@ -197,7 +198,10 @@ class HTTP {
197
198
* @returns {Promise<Response> }
198
199
*/
199
200
get ( resource , options = { } ) {
200
- return this . fetch ( resource , merge ( this . opts , options , { method : 'GET' } ) )
201
+ return this . fetch ( resource , {
202
+ ...options ,
203
+ method : 'GET'
204
+ } )
201
205
}
202
206
203
207
/**
@@ -206,7 +210,10 @@ class HTTP {
206
210
* @returns {Promise<Response> }
207
211
*/
208
212
put ( resource , options = { } ) {
209
- return this . fetch ( resource , merge ( this . opts , options , { method : 'PUT' } ) )
213
+ return this . fetch ( resource , {
214
+ ...options ,
215
+ method : 'PUT'
216
+ } )
210
217
}
211
218
212
219
/**
@@ -215,7 +222,10 @@ class HTTP {
215
222
* @returns {Promise<Response> }
216
223
*/
217
224
delete ( resource , options = { } ) {
218
- return this . fetch ( resource , merge ( this . opts , options , { method : 'DELETE' } ) )
225
+ return this . fetch ( resource , {
226
+ ...options ,
227
+ method : 'DELETE'
228
+ } )
219
229
}
220
230
221
231
/**
@@ -224,7 +234,10 @@ class HTTP {
224
234
* @returns {Promise<Response> }
225
235
*/
226
236
options ( resource , options = { } ) {
227
- return this . fetch ( resource , merge ( this . opts , options , { method : 'OPTIONS' } ) )
237
+ return this . fetch ( resource , {
238
+ ...options ,
239
+ method : 'OPTIONS'
240
+ } )
228
241
}
229
242
}
230
243
0 commit comments