Skip to content

Commit 27509b6

Browse files
committed
implement AbortController stub for node, react native & IE
1 parent b1f66ea commit 27509b6

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

src/createAsyncThunk.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import {
66
import { configureStore } from './configureStore'
77
import { AnyAction } from 'redux'
88

9+
import {
10+
mockConsole,
11+
createConsole,
12+
getLog
13+
} from 'console-testing-library/pure'
14+
915
describe('createAsyncThunk', () => {
1016
it('creates the action types', () => {
1117
const thunkActionCreator = createAsyncThunk('testType', async () => 42)
@@ -408,4 +414,46 @@ describe('createAsyncThunk with abortController', () => {
408414
meta: { aborted: true }
409415
})
410416
})
417+
418+
describe('behaviour with missing AbortController', () => {
419+
let keepAbortController: typeof AbortController
420+
let freshlyLoadedModule: typeof import('./createAsyncThunk')
421+
let restore: () => void
422+
let nodeEnv: string
423+
424+
beforeEach(() => {
425+
keepAbortController = window.AbortController
426+
delete window.AbortController
427+
jest.resetModules()
428+
freshlyLoadedModule = require('./createAsyncThunk')
429+
restore = mockConsole(createConsole())
430+
nodeEnv = process.env.NODE_ENV!
431+
process.env.NODE_ENV = 'development'
432+
})
433+
434+
afterEach(() => {
435+
process.env.NODE_ENV = nodeEnv
436+
restore()
437+
window.AbortController = keepAbortController
438+
jest.resetModules()
439+
})
440+
441+
test('calling `abort` on an asyncThunk works with a FallbackAbortController if no global abortController is not available', async () => {
442+
const longRunningAsyncThunk = freshlyLoadedModule.createAsyncThunk(
443+
'longRunning',
444+
async () => {
445+
await new Promise(resolve => setTimeout(resolve, 30000))
446+
}
447+
)
448+
449+
store.dispatch(longRunningAsyncThunk()).abort()
450+
// should only log once, even if called twice
451+
store.dispatch(longRunningAsyncThunk()).abort()
452+
453+
expect(getLog().log).toMatchInlineSnapshot(`
454+
"This platform does not implement AbortController.
455+
If you want to use the AbortController to react to \`abort\` events, please consider importing a polyfill like 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'."
456+
`)
457+
})
458+
})
411459
})

src/createAsyncThunk.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,34 @@ export function createAsyncThunk<
167167
}
168168
)
169169

170+
let displayedWarning = false
171+
172+
const AC =
173+
typeof AbortController !== 'undefined'
174+
? AbortController
175+
: class implements AbortController {
176+
signal: AbortSignal = {
177+
aborted: false,
178+
addEventListener() {},
179+
dispatchEvent() {
180+
return false
181+
},
182+
onabort() {},
183+
removeEventListener() {}
184+
}
185+
abort() {
186+
if (process.env.NODE_ENV === 'development') {
187+
if (!displayedWarning) {
188+
displayedWarning = true
189+
console.info(
190+
`This platform does not implement AbortController.
191+
If you want to use the AbortController to react to \`abort\` events, please consider importing a polyfill like 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'.`
192+
)
193+
}
194+
}
195+
}
196+
}
197+
170198
function actionCreator(arg: ThunkArg) {
171199
return (
172200
dispatch: GetDispatch<ThunkApiConfig>,
@@ -175,7 +203,7 @@ export function createAsyncThunk<
175203
) => {
176204
const requestId = nanoid()
177205

178-
const abortController = new AbortController()
206+
const abortController = new AC()
179207
let abortReason: string | undefined
180208

181209
const abortedPromise = new Promise<never>((_, reject) =>

0 commit comments

Comments
 (0)