74

There is a provision for try-catch block in javascript. While in java or any other language it is mandatory to have error handling, I don't see anybody using them in javascript for greater extent. Isn't it a good practice or just we don't need them in javascript?

4
  • 4
    While in java or *any other language* it is mandatory to have error handling... - Not really. Java, yes, but there are plenty of languages that don't insist on try-catch (like C#).
    – Jim G.
    Commented May 25, 2014 at 23:17
  • It is because you cannot use them in an async environment. I use them often by sync code by a lower abstraction level, for example by transforming something into something, etc...
    – inf3rno
    Commented May 26, 2014 at 3:27
  • I'll bet you see more try-catch's in server-side code than client-side code. Most of the cliend-side code you're privy to is doing nothing of importance. I'd wager minimizing KB down the pipe is more important than recovering from every error -- in most applications and browser-side circumstances.
    – svidgen
    Commented Jan 16, 2018 at 22:27
  • There is one other way to avoid try catch using maybe and Either (monads) we had a web scrapper written in node. We were able to remove all of try catch using it.
    – user93
    Commented Mar 1, 2018 at 2:59

7 Answers 7

72

One should avoid throw errors as the way to pass error conditions around in applications.

The throw statement should only be used "For this should never happen, crash and burn. Do not recover elegantly in any way"

try catch however is used in situation where host objects or ECMAScript may throw errors.

Example:

var json
try {
    json = JSON.parse(input)
} catch (e) {
    // invalid json input, set to null
    json = null
}

Recommendations in the node.js community is that you pass errors around in callbacks (Because errors only occur for asynchronous operations) as the first argument

fs.readFile(uri, function (err, fileData) {
    if (err) {
        // handle
        // A. give the error to someone else
        return callback(err)
        // B. recover logic
        return recoverElegantly(err)
        // C. Crash and burn
        throw err
    }
    // success case, handle nicely
})

There are also other issues like try / catch is really expensive and it's ugly and it simply doesn't work with asynchronous operations.

So since synchronous operations should not throw an error and it doesn't work with asynchronous operations, no-one uses try catch except for errors thrown by host objects or ECMAScript

13
  • 4
    I wouldn't go so far as to say no one uses try catch, it's just the wrong tool for the job in most cases. When there are truly exceptional circumstances, it can be worthwhile to throw an Error, but they are few and far between.
    – zzzzBov
    Commented Apr 13, 2012 at 16:56
  • 7
    @zzzzBov There's nothing wrong with throwing errors for case C, crash and burn. I just don't think you should catch errors and recover. For example document.getElementById doesn't throw when the element doesn't exist, it just returns null. The same can done for almost all cases
    – Raynos
    Commented Apr 13, 2012 at 17:07
  • 5
    @Raynos, throwing from a sync function is totally acceptable and makes sense in that use case. Returning error to callback is to async as throwing error is to sync.
    – sbartell
    Commented Oct 3, 2012 at 20:03
  • @Raynos have any good advice on avoiding using Errors/Exceptions for flow control on the client-side (non-Node environment)? I've found this post on StackOverflow, but it's mostly geared towards Java
    – blong
    Commented Apr 18, 2013 at 21:18
  • @b.long simple. don't throw errors ever. Problem solved.
    – Raynos
    Commented Apr 18, 2013 at 22:16
35

Try/catch in Javascript is not as bullet-proof as in other languages, due to Javascript's asynchronous nature. Consider this snippet:

try {
    setTimeout(function() {
        do_something_that_throws();
    }, 1000);
}
catch (e) {
    alert("You won't see this!");
}

The problem is that the control flow leaves the try block before do_something_that_throws() gets executed, so the error thrown inside the callback never gets catched.

So try/catch is basically inappropriate in many cases, and it's not always obvious whether something executes code asynchronously or not. Fortunately, javascript with its peculiar single-threaded-asynchronous-callback idiom and its support for actual closures provides an elegant alternative: continuation-passing style error handling. Just pass the proper response to any error as a function, e.g.:

setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);
10
  • 5
    it's not bullet proof in other languages either. Port that code to any language that supports asynchronous callbacks and it will fail too.
    – Raynos
    Commented Apr 13, 2012 at 22:23
  • 2
    @Raynos: You are right; however, other languages (or rather, their supporting cultures) do not buy this heavily into the asynchronous-callback idiom as Javascript does, and due to the multi-threaded nature of most other environments, the shortcomings of try/catch are more obvious and surrounded by lots of other caveats, so people naturally tread carefully in multi-threaded/asynchronous callback situations, and are more aware of potential pitfalls.
    – tdammers
    Commented Apr 15, 2012 at 12:21
  • Is this really due to JavaScript's "asynchronous nature?" As far as I can see, Try/Catch could theoretically be made to work lexically like how identifiers are lexically closed; it just doesn't happen to work that way in JavaScript.
    – Rag
    Commented Dec 3, 2012 at 10:00
  • 2
    In node.js >= 0.8 it is worth noting it is possible to try/catch asynchronously, please see my question stackoverflow.com/questions/14301839/… Commented Feb 1, 2013 at 3:41
  • 1
    This needs to include the current and more common async / await syntax in my opinion as the answer is out of date. Now that V8 has no performance issues with try...catch it is certainly not something to leave out and very useful in things like HTTP request handling
    – marksyzm
    Commented Jan 8, 2021 at 11:34
32

A lot of these answers are a bit old and do not take into account the new ES7 features async and await.

Using async/await you can now get asynchronous control flow like you want:

async function email(address) {
  try {
    // Do something asynchronous that may throw...
    await sendEmail({ to: address, from: '[email protected]', subject: 'Hello' })
  } catch(err) {
    if (err instanceof SomeCustomError) {
      elegantlyHandleError(err)
    } else {
      throw err
    } 
  }
})

You can learn more about async/await here, and you can use async/await now using babel.

4
  • But it is similar to a synchronous code Commented Jun 22, 2016 at 7:07
  • 2
    @AtulAgrawal yes, that is the point. Async/await allows you to write async code in a synchronous style so you can avoid "callback hell" and chaining lots of promises together. It's a very enjoyable way to write async code in my opinion Commented Jun 28, 2016 at 17:37
  • so what is the benefit of using javascript if we are making async code to synchronous. because most of the people use javascript due to its async nature Commented Jun 29, 2016 at 6:45
  • 3
    @AtulAgrawal you get the best of both worlds -- you enjoy async nature of the language (as the code above will still be executed async -- freeing the thread and all) and rip the benefits of a more programmer-friendly coding style. It's not without issues, though...
    – ZenMaster
    Commented Mar 24, 2017 at 16:39
18

try-catch in javascript is just as valid and useful as in any other language that implements them. There is one major reason its not used as much in javascript as in other languages. Its the same reason javascript is seen as an ugly scripting language, its the same reason as why people think javascript programmers aren't real programmers:

  • Javascript is an incredibly accessible and pervasive language

The mere fact that so many people are exposed to javascript (by virtue of the only supported language by browsers) means that you have lots of unprofessional code out there. Of course there are also many minor reasons:

  • some things in javascript are asynchronous and thus aren't catchable (asynchronous stuff)
  • there has been much overblown talk about how try-catch has a huge performance hit. It has a bit of a performance hit, but for most code, it is well worth it.
  • javascript was (unfortunately) implemented in a way that often silently ignores errors (automatically changing strings to numbers for example)

Regardless, try-catch should be used, but of course you should learn how to use them properly - like everything else in programming.

3
  • 4
    And why ever did you down downvote, oh silent downvoter?
    – user250878
    Commented May 24, 2014 at 20:34
  • Agreed. I think the accepted answer is generally true, but there are good reasons to use try-catch, and even throw, other than when dealing with native objects. When an error is thrown rather than passed to a callback, it halts further execution and jumps up the stack to the first block than can handle it. This is a great advantage and makes perfect sense for synchronous operations, especially if they involve deep nesting. It seems crazy to suggest exceptions are "bad" (well, other than for the obvious reasons) -- they're actually a very useful tool with a unique "power".
    – Semicolon
    Commented Oct 6, 2014 at 12:48
  • 2
    Did you ever take the time to read the source code of, say, jQuery? Hardly any try-catch in there except for exactly those scenario's mentioned in the accepted answer: to feature-detect and use native/host objects that throw errors. To call code that does not use try-catch much (like jQuery) 'unprofessional' seems silly. To be honest, I think that it's especially new Javascript programmers coming from Java that tend to over-use language features like try-catch. Commented May 25, 2015 at 20:31
6

I believe that much of the reason that try..catch is rare in JavaScript is because the language has a pretty high tolerance for error. The vast majority of situations can be handled by using code checks, good defaults, and asynchronous events. In some cases, simply using a pattern will prevent issues:

function Foo() {
    //this may or may not be called as a constructor!!
    //could accidentally overwrite properties on window
}

function Bar() {
    if (!(this instanceof Bar)) {
        return new Bar();
    }
    //this will only work on Bar objects, and wont impact window
}

Some of the major issues in other languages that cause exceptions to occur simply don't exist in JS. Type casting isn't needed the vast majority of the time. Instead, the preferred method is typically to feature check (enforcing a particular interface):

function doFoo(arg) {
    if (arg.foo) {
        arg.foo();
    } else {
        Bar.prototype.foo.call(arg);
    }
}

With the addition of async/await to the language, try..catch is becoming more prevalent. Promises being the asynchronous form of try..catch, it makes sense that one should expect:

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

to instead be written as:

try {
  const result = await doSomething()
  doSomethingWithResult(result)
} catch (e) {
  doSomethingWithError(e)
}
3

Possibly another reason try/catch is not used very much in Javascript is the construct wasn't available in the very first versions of Javascript ...it was added later.

As a result, some older browsers don't support it. (In fact, it may cause a parser/syntax error in some older browsers, something that's more difficult to "program defensively" against than most other types of errors.)

More importantly, since it wasn't available initially, the Javascript builtin functions that were initially released (what one would call the "library" functions in many languages) don't make use of it. (It doesn't work very well to "catch" an error from someobject.somefunction() if it doesn't "throw" but instead just returns "null" when it encounters a problem.)


Yet another possible reason is the try/catch mechanism didn't seem to be necessary initially (and still doesn't seem all that useful). It's really needed only when calls are routinely nested several levels deep; just returning some sort of ERRNO would work fine for direct calls (although to make it really useful whenever it's available, best practice in most languages is to use it everywhere rather than just on deeply nested calls). As Javascript logic was originally expected to be small and simple (after all, it's just an adjunct to a webpage:-), function calls weren't expected to be deeply nested, and so a try/catch mechanism didn't seem necessary.

1
  • 3
    No no no, absolutely not the case. Engines that old don't matter any more for a LONG time and the javascript community in general is quick to drop old things when justified. I would even bet that the majority of javascript developers now are post-IE6. Commented Dec 16, 2014 at 21:10
0

I believe they are not used that much because throwing exceptions in Javascript client side code makes it more difficult to debug a page.

Rather than throwing exceptions, I generally prefer to show al alert box, (i.e. alert("Error, invalid...");)

It might sound odd, but Javascript errors happen on client side, if a customers is using a page you built and the page throws an exception, unless the customer is a tech-savvy-coder there is no way he will ever be able to tell you what the issue is.

He will only call you in saying: "Hey, page X does not work!", and then it'll be all up to you to find what it went wrong and where in the code.

By using alert box instead it's more probable that he calls and says something like: "Hey, when I click on the button A of page X it shows a box that says...", trust me, it will be much easier to find the bug.

Not the answer you're looking for? Browse other questions tagged or ask your own question.