**finally** runs after the try and catch blocks, whether or not an error occurred, and even if there's a `return` in the try or catch. It's essential for cleanup: closing database connections, hiding loading spinners, releasing file handles. If finally itself throws, that new error replaces the previous one.
1Understanding finally Block
finally runs after the try and catch blocks, whether or not an error occurred, and even if there's a return in the try or catch. It's essential for cleanup: closing database connections, hiding loading spinners, releasing file handles. If finally itself throws, that new error replaces the previous one.
finally runs even after return statements in try/catch. The return value from finally overrides any return in try/catch — be careful.
async function fetchWithCleanup() {
let connection;
try {
connection = await openDB();
return await connection.query('SELECT * FROM users');
} catch (e) {
console.error('DB error:', e.message);
return [];
} finally {
// ALWAYS close connection, even on error
if (connection) await connection.close();
console.log('Connection closed');
}
}2Practical Example
Here is a real-world application of finally Block showing how it is used in production JavaScript code.
// finally with UI state
async function loadData() {
showSpinner();
try {
const data = await fetch('/api/data').then(r => r.json());
renderData(data);
} catch (e) {
showErrorMessage(e.message);
} finally {
hideSpinner(); // always hide, even on error
}
}3Best Practices
Follow these guidelines when working with finally Block:
1. Use finally for cleanup: connections, UI state, file handles
2. Keep finally blocks small and side-effect only
3. Don't return from finally unless intentional (it overrides try/catch return)
Tip: finally runs even after return statements in try/catch. The return value from finally overrides any return in try/catch — be careful.
async function fetchWithCleanup() {
let connection;
try {
connection = await openDB();
return await connection.query('SELECT * FROM users');
} catch (e) {
console.error('DB error:', e.message);
return [];
} finally {
// ALWAYS close connection, even on error
if (connection) await connection.close();
console.log('Connection closed');
}
}