You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/util/support/timeout.ts

79 lines
2.2 KiB

/**
* 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
*/
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
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
if ( timeout ) {
setTimeout(() => {
expired = true
if ( !resolved ) {
timeoutHandler()
}
}, timeout)
}
const result: T = await promise
resolved = true
if ( !expired ) {
await onTimeHandler(result)
} else {
await lateHandler(result)
}
return result
},
} as TimeoutSubscriber<T>
return sub
}