Grokking Advanced JavaScript
Vote

0% completed

​

try...catch...finally

The finally block

finally runs even when the function returns

Do not return from finally

When to use finally

What should a program do when some code must run whether an operation succeeds or fails? Suppose the shop shows a "Saving..." message while it saves an order. The message must disappear after a successful save, and it must also disappear after a failed one. If the program removes it only at the end of the try block, an error skips that line and the message stays on the screen.

The finally block

A finally block holds code that runs after the try block and the catch block, on every path through the statement.

try { // code that might throw an error } catch (error) { // code that runs only if the try block threw an error } finally { // code that runs last, whether or not an error was thrown }

The next program uses a variable, isSaving, in place of the on-screen message. It saves one valid order and one broken order.

Javascript
Javascript

. . . .
Saving started Saved: book Saving finished, isSaving is false Saving started Save failed: SyntaxError Saving finished, isSaving is false

In the first call, the try block succeeds, the catch block is skipped, and the finally block runs. In the second call, JSON.parse throws, the catch block runs, and then the finally block runs. The cleanup line is written once, and it runs in both cases.

Both the success path and the error path of saveOrder pass through the finally block before the function ends.
Both the success path and the error path of saveOrder pass through the finally block before the function ends.

The diagram shows the two calls side by side. The paths split after JSON.parse and join again at the finally block, which is why isSaving is false at the end of both.

finally runs even when the function returns

A finally block also runs when the try block or the catch block leaves the function early with return. The engine remembers the return value, runs the finally block, and only then returns the value to the caller.

Javascript
Javascript

. . . .
finally runs before readItem returns Item: book finally runs before readItem returns Item: unknown

The message from finally is printed before each item, because the caller receives the return value only after the finally block has finished. The same rule holds for break and continue inside a loop: the finally block runs before the loop moves on. It also holds when the catch block itself throws a new error. The finally block runs first, and then the new error continues to the caller.

Do not return from finally

A finally block can contain its own return statement, but it should not. A return in finally replaces the value that the try block returned, and it also cancels any error that the function was about to pass to its caller. The next function has no catch block, so it is a try...finally statement; that form is valid when you need cleanup but do not want to handle the error at this level.

Javascript
Javascript

. . . .
default default

The first call parsed the order correctly, yet it returns "default" instead of "book". The second call threw a SyntaxError, but the return in finally discarded it, so the caller never learns that the order text was broken. Keep finally blocks for cleanup only: reset a flag, close a connection, or stop a timer.

When to use finally

Use finally for code that must run after an operation no matter how the operation ended. Without it, you would have to copy the cleanup lines into the end of the try block and into the catch block, and a later change could easily update one copy and forget the other.

Do not use finally for code that should run only after success. That code belongs at the end of the try block, after the lines that can fail.

Reading Progress

0%


Vote for new content

On This Page

The finally block

finally runs even when the function returns

Do not return from finally

When to use finally