Why does a return in `finally` override `try`?

JavascriptReturnTry CatchTry Catch-FinallyTry Finally

Javascript Problem Overview


How does a return statement inside a try/catch block work?

function example() {
    try {
        return true;
    }
    finally {
        return false;
    }
}

I'm expecting the output of this function to be true, but instead it is false!

Javascript Solutions


Solution 1 - Javascript

Finally always executes. That's what it's for, which means its return value gets used in your case.

You'll want to change your code so it's more like this:

function example() { 
    var returnState = false; // initialization value is really up to the design
    try { 
        returnState = true; 
    } 
    catch {
        returnState = false;
    }
    finally { 
        return returnState; 
    } 
} 

Generally speaking you never want to have more than one return statement in a function, things like this are why.

Solution 2 - Javascript

According to ECMA-262 (5ed, December 2009), in pp. 96:

> The production TryStatement : try Block Finally is evaluated as follows: > > 1. Let B be the result of evaluating Block. > 2. Let F be the result of evaluating Finally. > 3. If F.type is normal, return B. > 4. Return F.

And from pp. 36:

> The Completion type is used to explain the behaviour of statements (break, continue, return and throw) that perform nonlocal transfers of control. Values of the Completion type are triples of the form (type, value, target), where type is one of normal, break, continue, return, or throw, value is any ECMAScript language value or empty, and target is any ECMAScript identifier or empty.

It's clear that return false would set completion type of finally as return, which cause try ... finally to do 4. Return F.

Solution 3 - Javascript

When you use finally, any code within that block fires before the method exits. Because you're using a return in the finally block, it calls return false and overrides the previous return true in the try block.

(Terminology might not be quite right.)

Solution 4 - Javascript

The finally block rewrites try block return (figuratively speaking).

Just wanted to point out, that if you return something from finally, then it will be returned from the function. But if in finally there is no 'return' word - it will be returned the value from try block;

function example() {
    try {
        return true;
    }
    finally {
       console.log('finally')
    }
}
console.log(example());
// -> finally
// -> true

So -finally- return rewrites the return of -try- return.

Solution 5 - Javascript

I'm gonna give a slightly different answer here: Yes, both the try and finally block get executed, and finally takes precedence over the actual "return" value for a function. However, these return values aren't always used in your code.

Here's why:

  • The example below will use res.send() from Express.js, which creates a HTTP response and dispatches it.
  • Your try and finally block will both execute this function like so:
try {
    // Get DB records etc.
    return res.send('try');
} catch(e) {
    // log errors
} finally {
    return res.send('finally');
}

This code will show the string try in your browser. ALSO, the example will show an error in your console. The res.send() function is called twice. This will happen with anything that is a function. The try-catch-finally block will obfuscate this fact to the untrained eye, because (personally) I only associate return values with function-scopes.

Imho your best bet is to never use return inside a finally block. It will overcomplicate your code and potentially mask errors.

In fact, there's a default code inspection rule set-up in PHPStorm that gives a "Warning" for this:

https://www.jetbrains.com/help/phpstorm/javascript-and-typescript-return-inside-finally-block.html

So what do you use finally for?

I would use finally only to clean-up stuff. Anything that is not critical for the return value of a function.

It may make sense if you think about it, because when you depend on a line of code under finally, you are assuming that there could be errors in try or catch. But those last 2 are the actual building blocks of error handling. Just use a return in try and catch instead.

Solution 6 - Javascript

why you are getting false is you returned in a finally block. finally block should execute always. so your return true changes to return false

function example() {
    try {
        return true;
    }
    catch {
        return false;
    }
}

Solution 7 - Javascript

As far as I know, the finally block always executes, irrespective of whether you have a return statement inside try or not. Ergo, you get the value returned by the return statement inside finally block.

I tested this with Firefox 3.6.10 and Chrome 6.0.472.63 both in Ubuntu. It is possible that this code may behave differently in other browsers.

Solution 8 - Javascript

> Returning from a finally-block > > If the finally-block returns a value, this value becomes the return > value of the entire try-catch-finally statement, regardless of any > return statements in the try and catch-blocks

Reference: developer.mozilla.org

Solution 9 - Javascript

Finally is supposed to ALWAYS run at the end of a try catch block so that (by specification) is why you are getting false returned. Keep in mind that it is entirely possible that different browsers have different implementations.

Solution 10 - Javascript

What about this?

doubleReturn();

function doubleReturn() {
  let sex = 'boy';

  try {
    return sex;

    console.log('this never gets called...');
  } catch (e) {} finally {
    sex = 'girl'; 

    alert(sex);
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbonfoView Question on Stackoverflow
Solution 1 - JavascriptannakataView Answer on Stackoverflow
Solution 2 - JavascriptlivibetterView Answer on Stackoverflow
Solution 3 - Javascriptdjdd87View Answer on Stackoverflow
Solution 4 - JavascriptMihey MikView Answer on Stackoverflow
Solution 5 - JavascriptFlameView Answer on Stackoverflow
Solution 6 - JavascriptanishMarokeyView Answer on Stackoverflow
Solution 7 - JavascriptManoj GovindanView Answer on Stackoverflow
Solution 8 - JavascriptThoView Answer on Stackoverflow
Solution 9 - JavascriptDarko ZView Answer on Stackoverflow
Solution 10 - JavascriptThomas KarlssonView Answer on Stackoverflow