@@ -76,17 +76,27 @@ export class NodeHttp2Handler implements HttpHandler {
76
76
}
77
77
}
78
78
const { requestTimeout, disableConcurrentStreams } = this . config ;
79
- return new Promise ( ( resolve , rejectOriginal ) => {
79
+ return new Promise ( ( _resolve , _reject ) => {
80
80
// It's redundant to track fulfilled because promises use the first resolution/rejection
81
81
// but avoids generating unnecessary stack traces in the "close" event handler.
82
82
let fulfilled = false ;
83
83
84
+ let writeRequestBodyPromise = Promise . resolve ( ) ;
85
+ const resolve = async ( arg : { response : HttpResponse } ) => {
86
+ await writeRequestBodyPromise ;
87
+ _resolve ( arg ) ;
88
+ } ;
89
+ const reject = async ( arg : unknown ) => {
90
+ await writeRequestBodyPromise ;
91
+ _reject ( arg ) ;
92
+ } ;
93
+
84
94
// if the request was already aborted, prevent doing extra work
85
95
if ( abortSignal ?. aborted ) {
86
96
fulfilled = true ;
87
97
const abortError = new Error ( "Request aborted" ) ;
88
98
abortError . name = "AbortError" ;
89
- rejectOriginal ( abortError ) ;
99
+ reject ( abortError ) ;
90
100
return ;
91
101
}
92
102
@@ -98,12 +108,12 @@ export class NodeHttp2Handler implements HttpHandler {
98
108
disableConcurrentStreams : disableConcurrentStreams || false ,
99
109
} as ConnectConfiguration ) ;
100
110
101
- const reject = ( err : Error ) => {
111
+ const rejectWithDestroy = ( err : Error ) => {
102
112
if ( disableConcurrentStreams ) {
103
113
this . destroySession ( session ) ;
104
114
}
105
115
fulfilled = true ;
106
- rejectOriginal ( err ) ;
116
+ reject ( err ) ;
107
117
} ;
108
118
109
119
const queryString = buildQueryString ( query || { } ) ;
@@ -138,7 +148,7 @@ export class NodeHttp2Handler implements HttpHandler {
138
148
req . close ( ) ;
139
149
const timeoutError = new Error ( `Stream timed out because of no activity for ${ requestTimeout } ms` ) ;
140
150
timeoutError . name = "TimeoutError" ;
141
- reject ( timeoutError ) ;
151
+ rejectWithDestroy ( timeoutError ) ;
142
152
} ) ;
143
153
}
144
154
@@ -147,17 +157,17 @@ export class NodeHttp2Handler implements HttpHandler {
147
157
req . close ( ) ;
148
158
const abortError = new Error ( "Request aborted" ) ;
149
159
abortError . name = "AbortError" ;
150
- reject ( abortError ) ;
160
+ rejectWithDestroy ( abortError ) ;
151
161
} ;
152
162
}
153
163
154
164
// Set up handlers for errors
155
165
req . on ( "frameError" , ( type : number , code : number , id : number ) => {
156
- reject ( new Error ( `Frame type id ${ type } in stream id ${ id } has failed with code ${ code } .` ) ) ;
166
+ rejectWithDestroy ( new Error ( `Frame type id ${ type } in stream id ${ id } has failed with code ${ code } .` ) ) ;
157
167
} ) ;
158
- req . on ( "error" , reject ) ;
168
+ req . on ( "error" , rejectWithDestroy ) ;
159
169
req . on ( "aborted" , ( ) => {
160
- reject ( new Error ( `HTTP/2 stream is abnormally aborted in mid-communication with result code ${ req . rstCode } .` ) ) ;
170
+ rejectWithDestroy ( new Error ( `HTTP/2 stream is abnormally aborted in mid-communication with result code ${ req . rstCode } .` ) ) ;
161
171
} ) ;
162
172
163
173
// The HTTP/2 error code used when closing the stream can be retrieved using the
@@ -169,11 +179,11 @@ export class NodeHttp2Handler implements HttpHandler {
169
179
session . destroy ( ) ;
170
180
}
171
181
if ( ! fulfilled ) {
172
- reject ( new Error ( "Unexpected error: http2 request did not get a response" ) ) ;
182
+ rejectWithDestroy ( new Error ( "Unexpected error: http2 request did not get a response" ) ) ;
173
183
}
174
184
} ) ;
175
185
176
- writeRequestBody ( req , request ) ;
186
+ writeRequestBodyPromise = writeRequestBody ( req , request , requestTimeout ) ;
177
187
} ) ;
178
188
}
179
189
0 commit comments