Skip to content

Commit eb11019

Browse files
authored
Merge pull request #4628 from andrejpavlovic/fix/timeout-on-createApi-endpoint-should-throw-TIMEOUT_ERROR
Fix `AbortError` being triggered incorrectly on `createApi` endpoint timeout
2 parents f009cc9 + d9a9106 commit eb11019

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

packages/toolkit/src/query/fetchBaseQuery.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ export function fetchBaseQuery({
213213
)
214214
}
215215
return async (arg, api) => {
216-
const { signal, getState, extra, endpoint, forced, type } = api
216+
const { getState, extra, endpoint, forced, type } = api
217217
let meta: FetchBaseQueryMeta | undefined
218218
let {
219219
url,
@@ -224,6 +224,14 @@ export function fetchBaseQuery({
224224
timeout = defaultTimeout,
225225
...rest
226226
} = typeof arg == 'string' ? { url: arg } : arg
227+
228+
let abortController: AbortController | undefined, signal = api.signal
229+
if (timeout) {
230+
abortController = new AbortController()
231+
api.signal.addEventListener('abort', abortController.abort)
232+
signal = abortController.signal
233+
}
234+
227235
let config: RequestInit = {
228236
...baseFetchOptions,
229237
signal,
@@ -272,10 +280,10 @@ export function fetchBaseQuery({
272280
let response,
273281
timedOut = false,
274282
timeoutId =
275-
timeout &&
283+
abortController &&
276284
setTimeout(() => {
277285
timedOut = true
278-
api.abort()
286+
abortController!.abort()
279287
}, timeout)
280288
try {
281289
response = await fetchFn(request)
@@ -289,6 +297,7 @@ export function fetchBaseQuery({
289297
}
290298
} finally {
291299
if (timeoutId) clearTimeout(timeoutId)
300+
abortController?.signal.removeEventListener('abort', abortController.abort)
292301
}
293302
const responseClone = response.clone()
294303

packages/toolkit/src/query/tests/createApi.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,3 +1147,38 @@ describe('custom serializeQueryArgs per endpoint', () => {
11471147
})
11481148
})
11491149
})
1150+
1151+
describe('timeout behavior', () => {
1152+
test('triggers TIMEOUT_ERROR', async () => {
1153+
const api = createApi({
1154+
baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com', timeout: 5 }),
1155+
endpoints: (build) => ({
1156+
query: build.query<unknown, void>({
1157+
query: () => '/success',
1158+
}),
1159+
}),
1160+
})
1161+
1162+
const storeRef = setupApiStore(api, undefined, {
1163+
withoutTestLifecycles: true,
1164+
})
1165+
1166+
server.use(
1167+
http.get(
1168+
'https://example.com/success',
1169+
async () => {
1170+
await delay(10)
1171+
return HttpResponse.json({ value: 'failed' }, { status: 500 })
1172+
},
1173+
{ once: true },
1174+
),
1175+
)
1176+
1177+
const result = await storeRef.store.dispatch(api.endpoints.query.initiate())
1178+
1179+
expect(result?.error).toEqual({
1180+
status: 'TIMEOUT_ERROR',
1181+
error: expect.stringMatching(/^AbortError:/),
1182+
})
1183+
})
1184+
})

0 commit comments

Comments
 (0)