- Home
- /
- Tutorials
- /
- JavaScript Tutorial
- /
- JavaScript finally
JavaScript Errors
JavaScript finally
finallyruns whether the code succeeded or failed.
It is for cleanup that must happen either way.
Hiding a loading spinner is the classic example.
Example
Example
javascript
const steps = [];
try {
steps.push("trying");
null.length;
} catch (error) {
steps.push("caught");
} finally {
steps.push("cleaned up");
}
console.log(steps.join(" "));The output is trying caught cleaned up.
When finally Runs
After the try block succeeds.
After the catch block handles an error.
Even when the function returns from inside the try.
Syntax
Syntax
javascript
try {
} catch (error) {
} finally {
// always runs
}finally can be used without a catch.
It Runs on Success Too
Nothing failed here, and the cleanup still happened.
Example
Example
javascript
const steps = [];
try {
steps.push("worked");
} catch (error) {
steps.push("failed");
} finally {
steps.push("cleaned up");
}
console.log(steps.join(" "));The output is worked cleaned up.
It Runs Before a Return
Even returning from inside the try does not skip it.
This surprises people the first time they see it.
Example
Example
javascript
const steps = [];
function run() {
try {
return "returned";
} finally {
steps.push("finally still ran");
}
}
const result = run();
console.log(result + " and " + steps[0]);The cleanup happened between the return and the caller receiving it.
Cleanup That Must Happen
Turning a loading flag off is the everyday use.
Example
Example
javascript
let loading = true;
try {
null.length;
} catch (error) {
// handled
} finally {
loading = false;
}
console.log(loading);The flag is cleared whichever way the code went.
try finally Without catch
The error still propagates, but the cleanup happens first.
Use this when you want to tidy up but not handle the failure here.
Example
Example
javascript
let cleaned = false;
let message;
try {
try {
null.length;
} finally {
cleaned = true;
}
} catch (error) {
message = "the error still escaped";
}
console.log(cleaned + " and " + message);The output is true and the error still escaped.
Do Not Return from finally
A return in finally overrides the one in try.
It can also swallow an error, which makes it genuinely dangerous.
Example
Example
javascript
function bad() {
try {
return "from try";
} finally {
return "from finally";
}
}
console.log(bad());The output is from finally, which is almost never what was intended.
Complete Example
Complete Example
html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript finally</title>
</head>
<body>
<h1>finally</h1>
<p id="out"></p>
<p id="status">Loading...</p>
<script>
const out = document.getElementById("out");
const status = document.getElementById("status");
try {
const data = JSON.parse("not json");
out.textContent = "Loaded " + data.name;
} catch (error) {
out.textContent = "Failed: " + error.name;
} finally {
status.textContent = "Finished";
}
</script>
</body>
</html>Try It Yourself
Run the above example in the Try It Editor.
Try valid JSON:
Fix the text and see that Finished still appears.
Important Points
finallyruns whether or not an error happened.- It runs even when the
tryblock returns. - It is the right place for cleanup.
try finallyworks without acatch.- Never return from a
finallyblock.
Conclusion
finally guarantees that cleanup happens.
It removes the need to repeat the same tidy-up in both branches.
Returning from it is the one thing to avoid.
