Skip to content

Instantly share code, notes, and snippets.

@glmdev
Created July 30, 2020 15:11
Show Gist options
  • Save glmdev/526c8b50fd7a276068cf43d634808973 to your computer and use it in GitHub Desktop.
Save glmdev/526c8b50fd7a276068cf43d634808973 to your computer and use it in GitHub Desktop.
TypeScript/JavaScript timeout handler - withTimeout
/*
This is a simple function I wrote to make awaiting promises with timeouts easier.
Pass it in a timeout length and a promise, and you can attach handlers for when
the promise resolves on time, when it resolves late, and when the timeout expires.
Here's a snippet from one of my projects as an example:
withTimeout(request_timeout, this.kernel.handle(req))
.on_time(output_req => { // called if it resolves on time
output_req.response.send()
})
.late(output_req => { // called if it resolves late
this.logger.error(`Request timed out. Response was already sent on path: ${req.path}. Consider increasing server.request_timeout.`)
})
.timeout(async () => { // called when the timeout expires
const factory = http(HTTPStatus.REQUEST_TIMEOUT)
const output_req = await factory.write(req)
output_req.response.send()
})
.run()
Copyright (C) 2020 Garrett Mills <garrett@garrettmills.dev>.
Licensed under the terms of the MIT license.
*/
export interface TimeoutSubscriber<T> {
on_time: (handler: (arg: T) => any) => TimeoutSubscriber<T>,
late: (handler: (arg: T) => any) => TimeoutSubscriber<T>,
timeout: (handler: () => any) => TimeoutSubscriber<T>,
run: () => Promise<T>,
}
export function withTimeout<T>(timeout: number, promise: Promise<T>) {
let on_time_handler: (arg: T) => any = (arg) => {}
let late_handler: (arg: T) => any = (arg) => {}
let timeout_handler: () => any = () => {}
const sub = {
on_time: handler => {
on_time_handler = handler
return sub
},
late: handler => {
late_handler = handler
return sub
},
timeout: handler => {
timeout_handler = handler
return sub
},
run: async () => {
let expired = false
let resolved = false
setTimeout(() => {
expired = true
if ( !resolved ) timeout_handler()
}, timeout)
const result: T = await promise
resolved = true
if ( !expired ) {
await on_time_handler(result)
} else {
await late_handler(result)
}
return result
}
} as TimeoutSubscriber<T>
return sub
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment