TaskWrite withSpinner(work) that logs 'spinner on', calls work() in try/catch/finally, logs 'caught: ' + err.message if it throws, and logs 'spinner off' in finally β re-throw the error after. Call it with work = () => { throw new Error('boom') } inside an outer try/catch; outer catch logs 'outer: ' + err.message.
try / catch / finally
100 XP7 min
Theory
finally runs always
finally runs whether or not the try threw β even if the catch threw, even if a return happened. It's the only safe place for cleanup that MUST happen.
function withConnection(work) {
const conn = openConnection();
try {
return work(conn);
} catch (err) {
console.error("work failed:", err);
throw err;
} finally {
conn.close(); // ALWAYS runs
}
}Common shape
The "wrap a risky thing, always tear it down" pattern:
- Open a file β finally close it.
- Start a transaction β finally rollback if not committed.
- Show a spinner β finally hide it.
Re-throwing
throw err inside a catch re-throws the same error. The finally still runs first; then the throw propagates to the caller. The original stack is preserved.
return inside finally is a trap
return inside finally overrides any return from try/catch and silently swallows pending throws. Always use finally for SIDE EFFECTS, never for return values.
π
Sign up to start coding
Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β card required, cancel anytime.
Sign up β free trial βFirst 15 lessons in each track are free. No card needed for those.