Skip to content

Instantly share code, notes, and snippets.

@lubieowoce
Created April 14, 2025 01:09
Show Gist options
  • Save lubieowoce/e98fd768a2c7ab5ea569d34bd6a77e72 to your computer and use it in GitHub Desktop.
Save lubieowoce/e98fd768a2c7ab5ea569d34bd6a77e72 to your computer and use it in GitHub Desktop.
try-catch-finally, sync and async
/** A `try-catch-finally` that works for both sync and async callbacks. */
export function tryCatch<T>(
cb: () => T | Promise<T>,
options: { catch?: (error: unknown) => T; finally?: () => void }
): T {
const { catch: onCatch, finally: onFinally } = options
let isAsync = false
try {
const result = cb()
if (isPromise(result)) {
let promise = result as Promise<T>
isAsync = true
if (onCatch) {
promise = promise.catch(onCatch)
}
if (onFinally) {
promise = promise.finally(onFinally)
}
return promise as T
} else {
return result
}
} catch (err) {
// if it threw, it can't be async.
if (onCatch) {
return onCatch(err)
} else {
throw err
}
} finally {
if (onFinally && !isAsync) {
onFinally()
}
}
}
function isPromise(result: unknown): result is Promise<unknown> {
return !!(
result &&
typeof result === 'object' &&
'then' in result &&
typeof result.then === 'function'
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment