-
Notifications
You must be signed in to change notification settings - Fork 156
Expand file tree
/
Copy pathabort.ts
More file actions
77 lines (66 loc) · 1.95 KB
/
abort.ts
File metadata and controls
77 lines (66 loc) · 1.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
* use non-native event emitter for the benefit of non-node runtimes like CF workers.
*/
import { Emitter } from '@segment/analytics-core'
import { detectRuntime } from './env'
/**
* adapted from: https://www.npmjs.com/package/node-abort-controller
*/
class AbortSignal {
onabort: globalThis.AbortSignal['onabort'] = null
aborted = false
eventEmitter = new Emitter()
toString() {
return '[object AbortSignal]'
}
get [Symbol.toStringTag]() {
return 'AbortSignal'
}
removeEventListener(...args: Parameters<Emitter['off']>) {
this.eventEmitter.off(...args)
}
addEventListener(...args: Parameters<Emitter['on']>) {
this.eventEmitter.on(...args)
}
dispatchEvent(type: string) {
const event = { type, target: this }
const handlerName = `on${type}`
if (typeof (this as any)[handlerName] === 'function') {
;(this as any)[handlerName](event)
}
this.eventEmitter.emit(type, event)
}
}
/**
* This polyfill is only neccessary to support versions of node < 14.17.
* Can be removed once node 14 support is dropped.
*/
class AbortController {
signal = new AbortSignal()
abort() {
if (this.signal.aborted) return
this.signal.aborted = true
this.signal.dispatchEvent('abort')
}
toString() {
return '[object AbortController]'
}
get [Symbol.toStringTag]() {
return 'AbortController'
}
}
/**
* @param timeoutMs - Set a request timeout, after which the request is cancelled.
*/
export const abortSignalAfterTimeout = (timeoutMs: number) => {
if (detectRuntime() === 'cloudflare-worker') {
return [] // TODO: this is broken in cloudflare workers, otherwise results in "A hanging Promise was canceled..." error.
}
const ac = new (global.AbortController || AbortController)()
const timeoutId = setTimeout(() => {
ac.abort()
}, timeoutMs)
// Allow Node.js processes to exit early if only the timeout is running
timeoutId?.unref?.()
return [ac.signal, timeoutId] as const
}