DEV Community

Stop Using Try-Catch: A Better Way to Handle Errors in JavaScript

Richard Shaju on November 03, 2024

JavaScript developers, there’s a new way to handle errors without relying on messy, repetitive try-catch blocks. Meet the Safe Assignment Operator ...
Collapse
 
jonrandy profile image
Jon Randy 🎖️

This operator is a very long way from becoming part of the language, if it ever does. It's from a DRAFT proposal that hasn't even been accepted for consideration yet, let alone inclusion.

Collapse
 
bloodbaz2 profile image
Chris Walsh

Articles like this always seem to gloss over this point which is really annoying.

Collapse
 
chani_diakidis_b2ab80f78f profile image
Chani Diakidis

I just wish that people stop using stop doing/using [placeholder].

Collapse
 
khuongduybui profile image
Duy K. Bui

Totally agreed. Just because there is a new alternative that is applicable in some use cases doesn't mean everyone should abandon the status quo.

Collapse
 
ozzythegiant profile image
Oziel Perez

That's modern React in a nutshell

Thread Thread
 
kbirgerdev profile image
Kirill Birger

Modern react is an oxymoron. React is a framework that is permanently stuck in some sort of dystopian alternate history universe

Thread Thread
 
adrian_zochowski_f7f740b2 profile image
Adrian Zochowski

Calling React a framework is like comparing a cat to a mouse. If you can't figure out that much, why even try to make any other comparison's.

Collapse
 
jeydotc profile image
Jeysson Guevara

From the creators of "you're doing [placeholder] wrong" and "[placeholder-1] will change [placeholder-2] forever", Clickbaity studios! 🤣

Collapse
 
btsncollins profile image
Nathan Collins • Edited

It's one of the reasons I deleted my Medium account and now it's permiating here too.

Stop telling us what totally normal and absolutely fine thing is bad.

Collapse
 
kovesp profile image
Peter Koves

Maximally agree. I search for "Stop Using on this site, and got 50+ hits.

Collapse
 
josiahbryan profile image
Josiah Bryan

Why? You mean like for the returning another error or something? Not sure why that's a problem, honest question, just curious what you're thinking?

Collapse
 
return215 profile image
The Returning Soul

No, OP commenter meant to not use such phrase for clickbait article title

Collapse
 
dinma_zilla_4272b654a3e17 profile image
Dinma Zilla

The second example is somewhat confusing to read. The Try/Catch syntax is very intuitive. 👍🏼

Collapse
 
magic_weaver09 profile image
Magic Weaver • Edited

great article! for anyone wanting to try a similar approach to the ?= operator now, i created safe-wrapper to handle errors gracefully. inspired by the safe assignment operator proposal, safe-wrapper returns a tuple [error, result] for both synchronous and asynchronous functions, reducing try-catch blocks.

it also includes type-specific error catching, allowing you to specify which error types to handle, throwing any unexpected types, for precise error management.

check out the npm package and give it a try!

Collapse
 
richardshaju profile image
Richard Shaju

Thanks for sharing

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Clearly the efforts made towards "centralizing" the error handling code makes it more complex and less intuitive than the try..catch version. While I see some value in this potential new operator, I don't think it is such a game changer.

Collapse
 
sti_selini profile image
Sti Selini • Edited

I do not, and never will, use nested try catch within a function. I almost never use it serially unless there is a massive reason such as immediate recoverability from the error, or state rollback, or a darn good logical reason, which is almost never.

I can count on two hands the number of patterns I've violated this rule with in JavaScript, Java, C++ and other languages in the last 35 years.

The reason you need solutions like this is you're writing bad code to begin with and have poor error handling design.

Collapse
 
ctsstc profile image
Cody Swartz

You could give a library like TS Results or Never Throw a try which gives additional tooling and abstractions that provides some quality of life & niceties, which can be used right now.

Given that this is not currently implemented for LTS I would recommend an abstraction like a library which could later utilize this method under the hood if/when it makes sense.

Collapse
 
leob profile image
leob

What? This looks identical to a post that I saw on dev.to a few months ago - why and how is this being "recycled"? Besides, this isn't even an accepted proposal, let alone it's implemented in JS already, so it's misleading to say "stop doing this or that" when the alternative doesn't even work ...

Besides, people should stop writing article titles like "STOP using this ..." or "you MUST do that ..." - we're not toddlers, we can make our own decisions and trade-offs, rather than being patronized or being told what we "must" do (even more so when the actual information is inaccurate or misleading) ...

How and why did this article make it to the top of my "dev.to" feed? Pretty useless ...

Collapse
 
_c2fc0b323bf profile image
Sergei Kostov • Edited

I made an account just to write this!

How can I down vote this. What an awful idea! This is going backwards. This is de-evolution. Degradation. Only people who have never in their life had to program in a language who has no exceptions may propose things like this.
Stop it get some help!

Collapse
 
retakenroots profile image
Rene Kootstra

My take on this is that most code has to many try catches anyway. The example above could have been just one try catch
The file successfully loaded or not. The reason why it failed, a file load failure or parsing becomes clear from the error stack trace.

On the safe assignment operator itself. I kind a like it but not convinced it is a game changer

Collapse
 
cawoodm profile image
Marc

How is this better? Proper use of try catch results in clean code because you have zero error handling in your main code - it’s all at the bottom making the happy flow easier to read. Your example is just bad try catch usage and one can easily imagine bad usage of the new operator where you end up with an if after every command - the whole reason exceptions were invented.

Collapse
 
emwadde profile image
emwadde

Here is a better article to read about
[the same concept](dev.to/polakshahar/stopping-errors...

Collapse
 
spock123 profile image
Lars Rye Jeppesen

I am unsure how this makes the code simpler .
Often you want to propagate thrown errors to previous layers of code, ending up with a top level error handler

It seems this approach will require you to deal with the error where it happens, which will lead to MORE lines of code, and spreading of the error handling logic.

What am I missing?

Collapse
 
jesseditson profile image
Jesse Ditson

FWIW, language features like this are super fun, but as Jon Randy points out, not in the spec - and in this case, it is very unlikely to ever be accepted, as try expressions looks more likely to be the solution to block-based try/catch. I'm sure you'd get less push back if you changed the title of this article to something less clickbait-y like "exploring the ?= operator in javascript" or "how to use experimental safe assignment in javascript".

For those interested in more context, here's the proposal (note the author's warning at the top):
github.com/arthurfiorette/proposal...

Here's the larger discussion: github.com/arthurfiorette/proposal...

FWIW the proposal that (at the time of writing) looks most likely to make it into the language is actually a new try operator that works during assignment:

const [err, data] = try await mayFail();
Enter fullscreen mode Exit fullscreen mode

It's somewhat similar to your article above, so perhaps a note that we're likely to get this functionality in typescript and later ECMAScript somewhat soon, but that the operator itself is still being discussed. And of course, if you have strong opinions, join the discussion and voting on the proposal thread!

Collapse
 
patriziobruno profile image
Patrizio Bruno • Edited

You could have written the try-catch example in 5/6 lines of code, but decided to overcomplicate it just to make your case. Well done, I took the bait, this time 🙂 Another article like this and I delete my subscription.

Collapse
 
smolinari profile image
Scott Molinari

To everyone reading this, it is a proposal and the "?=" operator more than likely won't be used, because it too close to nullish coalescing assignment. The more agreed upon solution (currently) is something like:

const [error, data] = try mightFail();
const [error, data] = try await mightFail();
Enter fullscreen mode Exit fullscreen mode

See the draft: github.com/arthurfiorette/proposal...

Scott

Collapse
 
genexu profile image
Gene Xu

I don't think this will be a game-changer. It looks similar to Golang syntax but without a defer function, the one of important parts of error handling in the Golang world.

Golang example:

func some() (thing) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    defer src.Close()
}
Enter fullscreen mode Exit fullscreen mode

Actually, if you are using typescript, you can do something like this:

async function fetchData() {
    try {
        await yup.string().eamil.verifySomeValues();
        const data = await axios('fetch some data');
        // do something for data...
    } catch(err: unknow) {
        if (err instanceof AxiosError) {
            // handle axios errors
        }
        if (err instanceof yup.ValidationError) {
            // handle yup validation error
        }
        const e = err as Error
        // handle other exception errors
    }
}
Enter fullscreen mode Exit fullscreen mode

It's used in my recent project and is more readable for me.

Collapse
 
quintesse profile image
Tako Schotanus • Edited

Those two pieces of code are not equivalent, in the first you are distinguishing between the two different errors while in the second you aren't (and can't anymore, you've lost that information).

If you don't care about detecting different errors but just any error then the first example becomes just as simple as the second one.

In fact if you have more complex code with multiple places that can generate errors than the try-catch becomes simpler again because you could have a single try-catch block instead of needing if-statements for each.

So the operator might be nice in some circumstances (especially in JavaScript where most errors are untyped) but I don't see any real advantage, only a stylistic choice.

Collapse
 
mitch1009 profile image
Mitch Chimwemwe Chanza • Edited

I thought the reason is dangerous , if it's about readability haa check how spaghettish Java is 😆😆😆

Don't get me wrong am not criticizing your article. Infact I love it. Am just justifying how this operator could not be ideal

My opinion 🤣🤣

Collapse
 
silvermangb profile image
Greg Silverman

If each type of error is handled the same way, by logging for example, this operator makes the code cleaner. But if there are different recovery responses for different errors you would need if-then or if-then-else or switch statements, so, not cleaner.

Collapse
 
latkinsa profile image
Sergey Latkin

Is it a clickbait repost, or what?

It looks like a newly re-generated version of this post: dev.to/paharihacker/effortless-err...

Collapse
 
adderek profile image
Maciej Wakuła

readFile(...)
.then(data=>cfg=JSON.parse(data))
.then(runCode(cfg))
.catch(alert("an error") ;

You can use Promise syntax (but that is causing some other problems).
You can use try-catch (preferably dividing your code into smaller pieces).
You could use whatever unofficial extension that you create a polyfill for. Like "?=" which is not yet supported.

JavaScript has the flexibility of not using types (though you could use typescript, jsdoc and even check types during runtime). It offers multiple ways to solve different types of challenges - you just need to pick the best for your case and know what are the consequences (you sacrifice something to gain other thing).

I would not tell "don't ever use this feature". However I could list pros and cons of some features. I encourage you to look wider and check whether there are niche scenarios that could fit other options (or maybe your case is the niche?).

Collapse
 
kovesp profile image
Peter Koves

What a strikingly modern approach!

I remember this kind of advice from the start of my IT career in the 1970-s.
"There is a return code from every system call. Be sure to check it after each call and take appropriate action if an error is indicated."
Mind you, when code was presented in articles like this, the error handling was omitted for clarity.

Collapse
 
amrikasir profile image
Al Amrikasir

Creative approach, if using try-catch statement just for one-line code like "just" fetching URL or open file etc etc, its a good way.

Try-Catch still used to handle many statements, fetching URL, parsing JSON, save or update to DB, or forward response to another URL.

Just like ternary operator, bool ? If-true : if-false, it's good to handle one-line statement.

Anyway, this is good thread, new way to handle things is one of the best part of programming 🍻🍻🍻

Collapse
 
nope12345 profile image
No • Edited

It's a bad example in the first place because you're just recreating built-in error handling, but if you really needed something like that:

const fileContents = await readFile('config.json')
  .catch(err => console.error('Error reading file:', err));
const config = fileContents && await Promise.try(() => JSON.parse(fileContents))
  .catch(err => console.error('Error parsing file:', err))

config && console.log('Configuration loaded successfully:', config);
Enter fullscreen mode Exit fullscreen mode

Promise.try isn't supported in Safari but you can either polyfill it, or use new Promise(r => r(JSON.parse(...)))

Collapse
 
kbirgerdev profile image
Kirill Birger

This is impractical beyond belief.

You are now writing extra code for conditions which should never occur.

If there's a readError, you should not ever get to the code that would generate a parseError. That's what try catch achieves. It may feel unwieldy, because of the nesting, but in this example it is more effective and manageable.

You could simply use try-catch to provide the same pattern of returning an error object instead of a result from the function that reads a file.

See: fantasyland, result pattern, either pattern
Seealso: fp-ts, purify-js

Collapse
 
click2install profile image
click2install

If developers would stop using errors for control flow you wouldn't need this crap scattered throughout your code in the first place. Maybe next time, at least wait until it's supported in Typescript - then it'll be widely accepted as a standard as it will be past Stage 3.

Collapse
 
yonatan_galili_391cc0f95a profile image
Yonatan Galili

Stop using clickbait to waste my time.

Please avoid using clickbait that wastes readers' time. Clearly state at the beginning of the article if it is a proposal, so readers don’t have to sift through comments to discover this only after investing time. While well meant, with limited time and attention, articles like these can be really frustrating.

Collapse
 
padmanabhan_s_ab4d1c7f349 profile image
Padmanabhan S

I can't get it together please help help me here , so based on this article , the async functions returns array now for destructuring ?, If it is why the '?' before '=', I think this '?=' Is bit far, cause even we use '?=' We have to wrap the logic under an if condition like they explained above in the example . Normally '? ' represent ' likely if ' for eg Ternary operator .
I know I am not that much of developer , so please hammer some reason behind his into me thanks in advance.

Iam sorry if I used harsh words, cause Iam new to comment, I'm still learning.🙏

Collapse
 
warmftsquared profile image
warmfeet • Edited

This is what happens when the third world starts trying to code.
Can't tell you how many times we've had to throw away code that some third worlder visa recipient contracted from his home country of third worlders, millions of dollars wasted, for Americans to clean up the mess.

Get out of here with this junk

Collapse
 
riccardobasile profile image
Riccardo Basile

Another article in which the autor ditches on a topic in favor of a "NEW STILL NOT SUBMITTED PROPOSAL", claiming that is the new game changer.

PLEASE - stop producing this kind of garbage - people end trusting you.

OR - write it as it is: "there is a guy with an idea, this is the github project pahe with his proposal still in draft that..." and you explain what you are referring to and your excitation for the topic.

BUT passing the thing as if it was already in the JS spec is a clickbaitish strategy
OR it could be a strategy to spread the topic and get more people pushing for its proposal - idk

TO ME: I'm reporting this article as scam.

Collapse
 
danielle_brear_584761b826 profile image
Danielle Brear

This is neat but readability is lost. The try/catch flow is vertically longer but it’s so much easier to follow. Expecting people to know that this operator somehow makes js into golang is going to confuse more people than it impresses.

Collapse
 
guy_nicholas_d4743d0ac80c profile image
Guy Nicholas

I'm sorry, but the example is lame. The nested try/catch handles a pair of errors differently, where the ?= example handles them as one. The original try/catch could have done exactly that by removing the inner try/catch.
Depending on the situation, I will sometimes nest the try/catch just to adjust the thrown error or to do some logging, and then re-throw. In my case I am writing server code and one error may be a 400 while another is a 500

Collapse
 
tsolan profile image
Eugene

It resembles Golang way but written quite awkwardly. Typically it should handle potential errors returned and terminate execution if any, then, proceed further.

Collapse
 
legregius profile image
David Guthrie

This is wrapping exceptions into old style return code errors. It's reliving all the mistakes of the 80s. The resulting code looks just like return codes, and then uses a contrived example of bad exception handling to make exceptions look worse. They each have their tradeoffs, but return codes nearly always result in more code.

Collapse
 
matthew_s_476c53e1c5fcc92 profile image
Matthew S

I wonder if there will be a performance penalty for using this like try catch has. If there isn't I would definitely be using the syntax. But I'm pretty sure like all new language features the engines have difficulties optimizing it over older and more well-known syntax. Ultimately I think this is just going to be syntactic sugar with the same caveats the old way of doing it.

Collapse
 
sardarjee profile image
Hari B

try ...catch ... finally is a proven statement. Messiness is just a relative term. From my experience, I am sure this operator can be a complement but not a replacement, at least for now.

I personally don't have any interest to replace try catch with it, but glad to see other perspectives.

Nice article!

Collapse
 
patrick_61cbc6392b72286f6 profile image
Patrick

Your writing is always engaging! I'd also like to recommend EchoAPI for JavaScript projects. It has truly enhanced my development experience, providing powerful tools for efficient API management.

Collapse
 
munenendereba profile image
Munene Ndereba

Inspired by go?

Collapse
 
adrian_zochowski_f7f740b2 profile image
Adrian Zochowski

I'm not sure where you got the examples but your if else is worst than the try catch itself. I suggest you learn basics first.

Collapse
 
haakontheadequate profile image
Haakon Hestness

Stop with the clickbait already. So annoying to see things that you can’t implement 💩🤬

Collapse
 
taufik_nurrohman profile image
Taufik Nurrohman

Actually, you could remove the nesting try/catch block and wrap the whole code with one try/catch block.

Collapse
 
thomdirac profile image
tomas-dirac • Edited

Is it deopt in v8? Try catch where optimized not that long before and its flaweless interesting how this behaves in performance critical code.

Collapse
 
jrrs1982 profile image
Jeremy Smith

Not for me, sorry.

Collapse
 
rroberrt profile image
Robert Sizarov

No, it’s not easier to read. It’s just a different way to note down the same thing. I don’t think the second example solves any problem.

Collapse
 
kristijanfistrek profile image
KristijanFištrek

Yeah, let's replace the simple try - catch with another hook logic. Perfect. Just what I needed.

Collapse
 
itay_yaffe_f09a9562fa5fd6 profile image
Itay Yaffe

Which browsers support this operator?

Collapse
 
dermorzi profile image
DerMorzi

Have you read the proposal? This syntax is deprecated, and the proposal is far away from be implemented in the runtimes. So this article has no value.

Collapse
 
hbthepencil profile image
HB_the_Pencil

This is neat! I haven't done much with try-catch in JS (I'm moving more towards Python), but this is cool. Is there a more efficient way to do this without having to define tons of variables?

Collapse
 
glittle profile image
Glen Little

Would be nice, but it doesn't exist today.

Collapse
 
wormss profile image
WORMSS

Are we just gonna ignore that you didn't await the fetch before requesting the json body?

Collapse
 
gs_da_blessed_fist profile image
Jason Zamora

It's like someone saying "You've been using the can opener the wrong way!" ..."Stop that, do this."

Collapse
 
cosma203 profile image
cosma203

I have a strong feeling this article is purely AI generated. Maybe i'm wrong. And if there is one term that screams AI to me, it's got to be game-changer. I'm honestly sick of that term. :D

Collapse
 
jafstar profile image
Jafar

I like it, ignore the doubters. Try/Catch is sloppy.

Collapse
 
whyte50 profile image
whyte50

I really don't see the point of this new syntax. It just puts all your code in one line, I don't believe it's as neat as try/catch and I can see it becoming very messy in the long run.

Collapse
 
marcio199226 profile image
oskar

it's better to use libs such as await-to-js imho

Collapse
 
spock123 profile image
Lars Rye Jeppesen

Or learn to write cleaner code, without nested try catches.

Collapse
 
cezary_mikoajczyk_66c13e profile image
Cezary Mikołajczyk • Edited

I think it's best for singular functions. It's hard to read big codebase with something like that. Really, depends on your app. Always keep the niche in mind.

Collapse
 
bumho12 profile image
Bum-Ho12

It simplifies the structure but increases difficulty in readability

Collapse
 
niallermoran profile image
Niall Moran

Feels a little like on error resume next in the very old days of VB. If I don't check the error variable my code keeps running? Source of a lot of dangerous bugs.

Collapse
 
keyhan profile image
KEYHAN

nice option 👍 thanks for the article
but it looks a little bit "unmaintainable" for me.

Collapse
 
eliza_begum_2881 profile image
Eliza Begum

Thanks for sharing. Keep it up 👍

Collapse
 
debasis_mallick_5d9b5da21 profile image
Debasis Mallick

Looka like dynamic proxy and centralized interceptor...nothing fancy

Collapse
 
abhishek_kumarsingh_9b5a profile image
Abhishek Kumar Singh

Totally Agree

Collapse
 
ziad_eltaher_80cedb1dd67 profile image
Ziad El Taher

Nice ❤️

Collapse
 
calabiyauman profile image
Düg

Now you have to set the initial state of every error type before youll see the error. How is this better?

Collapse
 
motimash profile image
motimash

Another junior developer.
I am not sure what was your point.

Collapse
 
jnp95 profile image
Jean-Noël

Nice to know!

Collapse
 
edward_hall_4ad7d19043b26 profile image
Edward Hall • Edited

Kinda like error handling in Go. I might be wrong thou

Collapse
 
z_eduardo_6e6da1daaa309b profile image
Zé Eduardo

Less typing just a progress.

Collapse
 
araz profile image
Araz

i wish the Internets add the dislike button again so we can down vote this article for not saying that this is experimental

Collapse
 
dheeraj_tp_4fb9f37e3fb0d9 profile image
Dheeraj TP

Why can't we simplify the code into smaller modules and then use try catch in each modules? That will be more readable i guess.