finally in JavaScript: the block that runs in every case

The finally block runs in every case, with or without an error and even after a return: this is where you properly close what was opened.
3 min read
Believemy logo

A program that opens something has to close it again: a loading indicator, a lock, a connection. The closing line always comes after the work, and an error raised during that work carries it away.

finally answers that precise problem, and no other: it reserves a zone that nothing can skip.


Definition

finally ends a try structure and runs whatever happens: the work succeeded, an error was caught by a catch, an error was caught by nobody, or the function left early through a return. No other block offers that guarantee.

JAVASCRIPT
let spinnerVisible = false;

function load(read) {
  spinnerVisible = true;
  try {
    return read();
  } finally {
    spinnerVisible = false;
  }
}

try {
  load(() => { throw new Error("network unavailable"); });
} catch (error) {
  console.log(error.message, "| spinner still visible:", spinnerVisible);
}
// network unavailable | spinner still visible: false

The indicator is removed even though the read failed, which a line placed after the structure would not have guaranteed.


It runs even after a return

This is the behavior that surprises people most, and the one that makes the block genuinely useful. It is tempting to picture a return ending the function on the spot. That is not what happens.

JAVASCRIPT
function value() {
  try {
    return "came from the try";
  } finally {
    console.log("the finally runs first");
  }
}

console.log(value());
// the finally runs first
// came from the try

The engine evaluates the expression after the return, sets the result aside, runs the finally, then hands the value back. The same mechanism applies to break and continue inside a loop.

Good to know

Never write a return inside the finally. It overwrites the value prepared by the try and, far worse, it makes a live error disappear: the function quietly returns a wrong result. A throw written there causes the same erasure.


The exact order of execution

When a structure brings all three blocks together, saying from memory which one runs first quickly becomes guesswork. Each row of the table reads as a timeline.

SituationWhat runs, in order
No errortry, then finally
Caught errortry up to the error, then catch, then finally
Uncaught errortry up to the error, then finally, then the error leaves
Exit through returntry up to the return, then finally, then the value leaves

The third row is the one that matters most in production: cleanup happens before the caller receives anything at all. One point often forgotten: an error raised inside the catch also triggers the finally before leaving.


Frequently asked questions

Question

Can a finally be written without a catch?

Yes, the form is valid and in fact very common. It says something precise: this function makes no claim to handle the error, it lets it travel up to the code that will, but it insists on tidying up before it goes.


Question

Does the block run when the error is caught nowhere?

Yes, in full, and then the error carries on up to the console or to the end of the process. The only situations that prevent it fall outside the language: a closed tab, a process killed by the operating system, a power cut.


Question

How is it different from a line written after the structure?

A line placed after the block runs only if execution reaches it. It is therefore skipped by a return, by an uncaught error, and by an error raised from the catch. The finally covers all three paths, which makes it the only safe place for cleanup that must happen.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.