Skip to main content

JavaScript Errors

JavaScript finally

Written by Published

finally runs 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

  • finally runs whether or not an error happened.
  • It runs even when the try block returns.
  • It is the right place for cleanup.
  • try finally works without a catch.
  • Never return from a finally block.

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.