DEV Community

Cover image for The `finally` Block in `try-catch-finally` Executes Always
Vishnu Haridas
Vishnu Haridas

Posted on

The `finally` Block in `try-catch-finally` Executes Always

This article shows Javascript examples. I tried this in Javascript, Java, and Kotlin. A more Kotlin-centric approach in my personal blog.


Recently I was exploring some source code and came across a code that implements a Mutex.

Here's what it looks like (from kotlinx-couroutines-core)

    lock(owner)
    try {
        return action()
    } finally {
        unlock(owner)
    }

I was wondering how they are going to release the mutex lock within the finally block once the return action() inside the try block is executed.

I never wrote a finally block before, so this got me a little confused.

A search revealed that many people have come across this situation. There's a question in StackOverflow which has around ~2.4k upvotes and bookmarked ~500 times.

It is true. The finally block gets executed always, except some unforeseen situations like the process getting killed, which is mentioned in the accepted answer in the StackOverflow question.

I looked up in the MDN documentation and found this:

"Note that the finally-block executes regardless of whether an exception is thrown. Also, if an exception is thrown, the statements in the finally-block execute even if no catch-block handles the exception."

Let's try out a try block!

So I created a small JSBin snippet to test that:

function tryExample(){
  try{
    return "Returned from try{}";
  } finally {
    console.log("Inside finally{}");
  }
}

console.log(tryExample());

This code will print:

Inside finally{}
Returned from try{}

One more thing, if the finally returns something, then the return within the try block won't work.

When I posted this on LinkedIn, my colleague Afsal pointed out another interesting thing -- if we return from the finally block, then the return statement within the try block won't execute.

That was another discovery.

I created another JSBin snippet to test that:

function finallyReturnsExample(){
    try{
        return "Returned from try{}"
    } finally {
        console.log("Inside finally{}")
        return "Returned from finally{}"
    }
}

console.log(finallyReturnsExample());

The output will be:

Inside finally{}
Returned from finally{}

So a new lesson learned - the finally block always executes (except for a few conditions) and if a finally block returns, the try/catch won't return.

Top comments (0)