@@ -62,6 +62,7 @@ const connectH2 = require('./client-h2.js')
62
62
let deprecatedInterceptorWarned = false
63
63
64
64
const kClosedResolve = Symbol ( 'kClosedResolve' )
65
+ const kDrainQueue = Symbol ( 'kDrainQueue' )
65
66
66
67
function getPipelining ( client ) {
67
68
return client [ kPipelining ] ?? client [ kHTTPContext ] ?. defaultPipelining ?? 1
@@ -243,6 +244,14 @@ class Client extends DispatcherBase {
243
244
this [ kMaxConcurrentStreams ] = maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server
244
245
this [ kHTTPContext ] = null
245
246
247
+ // TODO (fix): What if destroyed?
248
+ this [ kDrainQueue ] = [ ]
249
+ this . on ( 'drain' , ( ) => {
250
+ for ( const callback of this [ kDrainQueue ] . splice ( 0 ) ) {
251
+ callback ( null )
252
+ }
253
+ } )
254
+
246
255
// kQueue is built up of 3 sections separated by
247
256
// the kRunningIdx and kPendingIdx indices.
248
257
// | complete | running | pending |
@@ -299,26 +308,31 @@ class Client extends DispatcherBase {
299
308
this . once ( 'connect' , cb )
300
309
}
301
310
302
- [ kDispatch ] ( opts , handler ) {
311
+ [ kDispatch ] ( opts , handler , onDrain ) {
303
312
const origin = opts . origin || this [ kUrl ] . origin
304
313
const request = new Request ( origin , opts , handler )
305
314
306
- this [ kQueue ] . push ( request )
307
- if ( this [ kResuming ] ) {
308
- // Do nothing.
309
- } else if ( util . bodyLength ( request . body ) == null && util . isIterable ( request . body ) ) {
310
- // Wait a tick in case stream/iterator is ended in the same tick.
311
- this [ kResuming ] = 1
312
- queueMicrotask ( ( ) => resume ( this ) )
315
+ if ( this [ kBusy ] && onDrain ) {
316
+ this [ kDrainQueue ] . push ( onDrain )
317
+ return false
313
318
} else {
314
- this [ kResume ] ( true )
319
+ this [ kQueue ] . push ( request )
320
+ if ( this [ kResuming ] ) {
321
+ // Do nothing.
322
+ } else if ( util . bodyLength ( request . body ) == null && util . isIterable ( request . body ) ) {
323
+ // Wait a tick in case stream/iterator is ended in the same tick.
324
+ this [ kResuming ] = 1
325
+ queueMicrotask ( ( ) => resume ( this ) )
326
+ } else {
327
+ this [ kResume ] ( true )
328
+ }
315
329
}
316
330
317
331
if ( this [ kResuming ] && this [ kNeedDrain ] !== 2 && this [ kBusy ] ) {
318
332
this [ kNeedDrain ] = 2
319
333
}
320
334
321
- return this [ kNeedDrain ] < 2
335
+ return onDrain ? true : this [ kNeedDrain ] < 2
322
336
}
323
337
324
338
async [ kClose ] ( ) {
0 commit comments