lib/src/util/support/timeout.ts

77 lines
2.1 KiB
TypeScript
Raw Normal View History

2021-06-02 01:59:40 +00:00
/**
* Base interface representing a timeout subscriber.
*/
export interface TimeoutSubscriber<T> {
/**
* Handler will execute if the promise resolves before the timeout occurs.
* @param handler
*/
onTime: (handler: (arg: T) => any) => TimeoutSubscriber<T>,
/**
* Handler will execute if the promise resolves after the timeout occurs.
* @param handler
*/
late: (handler: (arg: T) => any) => TimeoutSubscriber<T>,
/**
* Handler will execute if the promise has not resolved when the timeout occurs.
* @param handler
*/
timeout: (handler: () => any) => TimeoutSubscriber<T>,
/**
* Start the timer.
*/
run: () => Promise<T>,
}
/**
* Subscribe to a promise with a timeout.
* @param {number} timeout - timeout in milliseconds
* @param {Promise} promise - the promise to subscribe to
*/
2021-06-03 03:36:25 +00:00
export function withTimeout<T>(timeout: number, promise: Promise<T>): TimeoutSubscriber<T> {
let onTimeHandler: (arg: T) => any = () => {} // eslint-disable-line @typescript-eslint/no-empty-function
let lateHandler: (arg: T) => any = () => {} // eslint-disable-line @typescript-eslint/no-empty-function
let timeoutHandler: () => any = () => {} // eslint-disable-line @typescript-eslint/no-empty-function
2021-06-02 01:59:40 +00:00
const sub = {
onTime: handler => {
onTimeHandler = handler
return sub
},
late: handler => {
lateHandler = handler
return sub
},
timeout: handler => {
timeoutHandler = handler
return sub
},
run: async () => {
let expired = false
let resolved = false
setTimeout(() => {
expired = true
2021-06-03 03:36:25 +00:00
if ( !resolved ) {
timeoutHandler()
}
2021-06-02 01:59:40 +00:00
}, timeout)
const result: T = await promise
resolved = true
if ( !expired ) {
await onTimeHandler(result)
} else {
await lateHandler(result)
}
return result
2021-06-03 03:36:25 +00:00
},
2021-06-02 01:59:40 +00:00
} as TimeoutSubscriber<T>
return sub
}