181

I have a number of functions which either return something or throw an error. In a main function, I call each of these, and would like to return the value returned by each function, or go on to the second function if the first functions throws an error.

So basically what I currently have is:

function testAll() {
    try { return func1(); } catch(e) {}
    try { return func2(); } catch(e) {} // If func1 throws error, try func2
    try { return func3(); } catch(e) {} // If func2 throws error, try func3
}

But actually I'd like to only try to return it (i.e. if it doesn't throw an error). I do not need the catch block. However, code like try {} fails because it is missing an (unused) catch {} block.

I put an example on jsFiddle.

So, is there any way to have those catch blocks removed whilst achieving the same effect?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
pimvdb
  • 151,816
  • 78
  • 307
  • 352

13 Answers13

326

A try without a catch clause sends its error to the next higher catch, or the window, if there is no catch defined within that try.

If you do not have a catch, a try expression requires a finally clause.

try {
    // whatever;
} finally {
    // always runs
}
kennebec
  • 102,654
  • 32
  • 106
  • 127
  • 1
    So the best way would be to write something like`try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}`? – user2284570 Dec 16 '14 at 08:25
  • 3
    Above comment does not accurately answer OP because he doesn't want to run function 2 if function 1 succeeds. – Andrew Steitz Dec 06 '18 at 20:56
  • 6
    Note that a [try without a catch doesn't swallow errors](https://stackoverflow.com/questions/5764107/try-without-catch-possible-in-javascript/56404126#56404126). – Dan Dascalescu Jun 01 '19 at 05:41
  • Thank you that's what I needed :-) It would be really awesome if it also works without the try {} I mean: async () => { indicateWorkInProgress() await pipelineStep1() await pipelineStep2() ... finally { stopIndicator() } } It would be clear that the whole function is meant ;-) Those try blocks are so ugly there... – Lenny Jun 24 '19 at 20:16
126

It's possible to have an empty catch block, without an error variable, starting with ES2019. This is called optional catch binding and was implemented in V8 v6.6, released in June 2018. The feature has been available since Node 10, Chrome 66, Firefox 58, Opera 53 and Safari 11.1.

The syntax is shown below:

try {
  throw new Error("This won't show anything");
} catch { };

You still need a catch block, but it can be empty and you don't need to pass any variable. If you don't want a catch block at all, you can use the try/finally, but note that it won't swallow errors as an empty catch does.

try {
  throw new Error("This WILL get logged");
} finally {
  console.log("This syntax does not swallow errors");
}
Filip Š
  • 746
  • 2
  • 13
  • 22
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
  • 4
    this answer is the most up to date! in terms of execution order, 1. it attempts the `try` block. 2. Catches the error. 3. Executes the `finally` block. 4. Throws the error. Is this correct? – helsont Jun 20 '19 at 17:16
  • Thanks @helsont. As for the execution order in the second code sample, I'm not sure one can tell whether the error is caught and re-thrown, or just (probably) simply thrown and not caught in the first place (since there's no `catch`). [Surround the whole code with another `try`/`catch`](https://repl.it/repls/ElectronicMiserablePrediction) and you'll be able to catch the `This WILL get logged` error. – Dan Dascalescu Jun 21 '19 at 01:02
14

Nope, catch (or finally) is try's friend and always there as part of try/catch.

However, it is perfectly valid to have them empty, like in your example.

In the comments in your example code (If func1 throws error, try func2), it would seem that what you really want to do is call the next function inside of the catch block of the previous.

alex
  • 479,566
  • 201
  • 878
  • 984
  • 1
    You're correct. However if code like `try {...}; try {...}` would be possible, the meaning of the code might be clearer (try the first, otherwise try the second). – pimvdb Apr 23 '11 at 12:21
  • About your edit: In the JSFiddle example, the second function returns something, so is the third function really evaluated in that case? I thought a `return` statement stops anything coming after it. – pimvdb Apr 23 '11 at 12:23
  • 1
    @pimvdb Sorry, I didn't check the fiddle. `return` will cause the function to return prematurely. I will update my answer. – alex Apr 23 '11 at 12:23
  • 1
    This answer is factually incorrect, you can have `try {}; finally {}` as shown in http://stackoverflow.com/a/5764505/68210 – Daniel X Moore Feb 21 '14 at 21:59
  • 1
    @DanielXMoore Sure, it is, but `finally{}` is basically in the same spirit as `catch{}`. I'll update the answer. – alex Feb 23 '14 at 01:51
  • @pimvdb, if `try {…}; try {…}` were a legal syntax, I am quite sure it would/should behave identically to `try {…} finally{}; try {…} finally{}`, meaning that the exceptions are not caught. Generally, you should only catch expected exceptions (e.g., “found no ideal move”) so that “real” exceptional situations (e.g., “x is not a function”) don’t get silently eaten by your `try {…} catch (e) {…}` block. This is why the Mozilla internally has a non-standard syntax of `try {…} catch (e if e instanceof TypeError) {…}` and also why `try` can have `finally {}` with no `catch`. – binki Apr 02 '14 at 22:06
12

I wouldn't recommend try-finally without the catch, because if both the try block and finally block throw errors, the error thrown in the finally clause gets bubbled up and the try block's error is ignored, in my own test:

try {
  console.log('about to error, guys!');
  throw new Error('eat me!');
} finally {
  console.log ('finally, who cares');
  throw new Error('finally error');
}

Result:

>     about to error, guys!
>     finally, who cares
>     .../error.js:9
>         throw new Error('finally error');
>         ^
>     
>     Error: finally error
Joe B.
  • 1,153
  • 1
  • 10
  • 17
5

No, it is not possible to have try block without catch (or finally). As a workaround, I believe you might want to define a helper function such as this:

function tryIt(fn, ...args) {
    try {
        return fn(...args);
    } catch {}
}

and use it like:

tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);
Clokman
  • 303
  • 2
  • 11
Itay Merchav
  • 954
  • 8
  • 8
2

I've decide to look at the problem presented from a different angle.

I've been able to determine a way to to allow closely for the code pattern requested while in part addressing the un-handled error object listed by another commenter.

code can be seen @ http://jsfiddle.net/Abyssoft/RC7Nw/4/

try:catch is placed within a for loop allowing graceful fall through. while being able to iterate through all the functions needed. when explicit error handling is needed additional function array is used. in the even of error and functional array with error handlers element is not a function, error is dumped to console.

Per requirements of stackoverflow here is the code inline [edited to make JSLint compliant (remove leading spaces to confirm), improve readability]

function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }

// ctr = Code to Run <array>, values = values <array>, 
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
    "use strict";
    var cb; // cb = code block counter
    for (cb in ctr) {
        if (ctr.hasOwnProperty(cb)) {
            try {
                return ctr[cb](values[cb]);
            } catch (e) {
                if (typeof eh[cb] === "function") {
                    eh[cb](e);
                } else {
                    //error intentionally/accidentially ignored
                    console.log(e);
                }
            }
        }
    }
    return false;
}

window.alert(testAll([func1, func2, func3], [], []));

2

If you only want functions 2 and 3 to fire if an error occurs why are you not putting them in the catch block?

function testAll() {
  try {
    return func1();
  } catch(e) {
    try {
      return func2();
    } catch(e) {
      try {
        return func3();
      } catch(e) {
        // LOG EVERYTHING FAILED
      }
    }
  }
}
Tank
  • 29
  • 1
2

...is there any way to have those catch blocks removed whilst achieving the same effect? As it would seem, no; Javascript requires a try block be followed by either a catch or a finally block.

Having said that, there is a way to use those catch blocks to achieve the effect you want.

// If func1 throws error, try func2 The if throws error condition, is what the catch block is for.

Why remove them when their use is exactly what you are after?

try { return func1(); }
catch {
   // if func1 throws error
   try { return func2(); } 
   catch {
      // if func2 throws error
      try { return func3(); } 
      catch {
         // if func3 throws error
      }
   }
}

I completely understand why you might not need a catch block, and would find it cleaner to be able to omit it entirely. But I don't think this is one of those situations.

Air
  • 498
  • 1
  • 4
  • 18
0

Another way to mark empty block code in JS, you can use: /* empty */. I mean:

try {
    // your code here
} catch { /* empty */ }
Hungnn
  • 68
  • 1
  • 2
  • 19
-1

They go together in every language that I know that has them (JavaScript, Java, C#, C++). Don't do it.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 1
    Odd that mine was downvoted five years later when it says the same thing as other answers here. Mine appears to be the only one that was downvoted. Moderators, please take note. – duffymo Apr 25 '16 at 14:52
  • Tcl has a very convenient single-word construct `catch {my code}` – MKaama Oct 24 '16 at 12:38
  • [Starting with ES2019, catch binding is optional](https://stackoverflow.com/questions/5764107/try-without-catch-possible-in-javascript/56404126#56404126). – Dan Dascalescu Jun 01 '19 at 05:34
  • Why? Feels useless, unless it’s try/finally. – duffymo Jun 01 '19 at 13:05
-4

Since ES2019 you can easily use try {} without catch {}:

try {
  parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}

For more info please reffer to Michael Ficcara's proposal

JamesJGoodwin
  • 350
  • 1
  • 3
  • 17
-5

try & catch are like 2 side of one coin. so not possible without try.

Hitesh Prajapati
  • 2,762
  • 8
  • 23
  • 29
  • 6
    This answer is factually incorrect, you can have `try {}; finally {}` as shown in http://stackoverflow.com/a/5764505/68210 – Daniel X Moore Feb 21 '14 at 22:00
  • And [starting with ES2019, catch binding is optional](https://stackoverflow.com/questions/5764107/try-without-catch-possible-in-javascript/56404126#56404126). – Dan Dascalescu Jun 01 '19 at 05:34
-24

No. You have to keep them.

This actually makes sense since errors shouldn't be silently ignored at all.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • 1
    Why I'm using this currently is because I have several algorithms to determine the best move in a game. Sometimes, the tactic of `func1` has no best moves, so I'd like to move on to the second tactic tried in `func2`. Could you please tell me why this would be unadvisable? – pimvdb Apr 23 '11 at 12:29
  • 19
    In that case those functions should not throw errors but return e.g. `null` and you do something like `return func1() || func2() || func3();` – ThiefMaster Apr 23 '11 at 13:08
  • 61
    This answer is factually incorrect, you can have `try {}; finally {}` as shown in http://stackoverflow.com/a/5764505/68210 – Daniel X Moore Feb 21 '14 at 21:59
  • 3
    @DanielXMoore: But that's not really the point of the question. – ThiefMaster Feb 22 '14 at 03:50
  • 4
    @DanielXMoore, without the `catch (e) {}`, the exception thrown by `func1()` would prevent `func2()` from being tried. – binki Apr 02 '14 at 21:52
  • 84
    It sometimes makes perfect sense to have an empty catch, so I don't agree with your argument. – Petr Peller Jun 02 '16 at 13:33
  • 4
    ever used `JSON.parse`? It throws on a parse error but I cannot depend on incoming information to always parse 100% of the time so it has to be like this: `try {handleMessage( JSON.parse(message) )} catch (e) {}` I think it would be nice if js had an auto-catch if omitted. – ThaJay Feb 27 '17 at 13:34
  • 4
    @ThaJay exactly. As well, there are times where an object may or may not exist in a parent object (browser compatibility anyone?). Where its far easier to just `try { some.buried.object.method(); }` instead of doing a massive `typeof .. != 'undefined'` chain of `if` blocks. – IncredibleHat Dec 21 '17 at 17:01
  • 1
    @ThiefMaster there are some cases where errors are expected to be ignored silently. Where we expect we can fail and that is not a case to panic. – MrHIDEn Sep 24 '19 at 23:15
  • 13
    This answer is factually incorrect and misleading. "It actually makes sense" you say, but you're wrong, it only makes sense in some cases and not others. It's a great example of a terrible answer being accepted inexplicably. There are many cases where it makes sense to have no catch block, like in an `async` function, sometimes. Being forced by the javascript language to create empty `catch` blocks is *clearly* pointless. – ICW Sep 28 '19 at 19:15