gib
gib

Reputation: 788

Throw in try, catch, finally - weird behavior?

I don't understand why this:

try {
    throw 'err1';
} catch {
    throw 'err2';
} finally {
    throw 'err3';
}

Gives me this:

$ node try.js

/try.js:6
    throw 'err3';
    ^
err3

I would suspect, that I should get err2. I know that finally {} is always executed, whether try {} succeeded or not, but why exception from finally {} is returned before exception in catch {}?

Upvotes: 1

Views: 326

Answers (2)

Alex
Alex

Reputation: 21

A throw isn't an instantaneous thing. It's easy to feel like it when you don't have a finally block but the finally has the ability to change your throw (it can also change your return value!) and the value isn't handled until the function actually ends. (with some exceptions for thread termination, etc)

Upvotes: 0

str
str

Reputation: 45029

That is the behaviour as defined by the ECMAScript specification:

TryStatement : try Block Catch Finally

  1. Let B be the result of evaluating Block.
  2. If B.[[type]] is throw, then
    • Let C be CatchClauseEvaluation of Catch with parameter B.[[value]].
  3. Else B.[[type]] is not throw, let C be B.
  4. Let F be the result of evaluating Finally.
  5. If F.[[type]] is normal, let F be C.
  6. If F.[[type]] is return, or F.[[type]] is throw, return Completion(F).

[...]

This might be non-trivial to read. But the gist of it is that the result of the catch block is assigned to C. But if the finally returns anything or throws, C is ignored and the result of the finally is returned instead.

Upvotes: 2

Related Questions