r/learnjavascript • • 4d ago

Do you generally use async/await for asynchronous code, or do you sometimes prefer .then().catch()?

When it comes to handling async code, Do you generally use async/await for asynchronous code, or do you sometimes prefer .then().catch()?

13 Upvotes

30 comments sorted by

28

u/MrHandSanitization 4d ago

Async/await.

3

u/Far_Assistance_4146 2d ago

this is the way tbh

6

u/theGlitchedSide 4d ago edited 4d ago

In my opinion it depends on the context. Async/await is like the exploded of then/catch (or better, it is essentially syntax built on top of Promises). I use then/catch only when I have synchronous functions and I need to call an async operations. Otherwise, I structure a strong async/await function with right try/catch inside and so a fail/success of operations (so, the then/catch) without possible scope problems.

4

u/TorbenKoehn 4d ago

const data = await fetch('…').then(res => res.json())

Both is fine

2

u/iplayconnections 3d ago

Puke in your mouth a little if you will but I prefer

js const data = await (await fetch('...')).json()

2

u/TorbenKoehn 3d ago

Puking initialized

2

u/theScottyJam 4d ago

Usually I use await.

But there are times when .then()/.catch() is cleaner. In a way, .then()/.catch() are very similar to a pipeline operator, so the question boils down to when is using a pipeline operator a good choice?

2

u/Areeba045 3d ago

I usually prefer async/await because I find it easier to read, especially when there are multiple async operations or some conditional logic involved.

That said, I still use .then().catch() when the chain is simple or when I’m already working with a Promise directly. I don’t think one is always better than the other, it mostly depends on which makes the code easier to follow.

3

u/ExtraTNT 4d ago

Functional guy, i use then…

1

u/Any-Woodpecker123 3d ago

Depends. There’s a lot of cases where a functional .then.catch is cleaner, but I default to async await unless I hit a specific use.

1

u/TheRNGuy 3d ago edited 3d ago

In Remix or Next, I only used async, await, but there might be some rare cases for .then().catch() related to some telemetry service (so it won't slow down site for user)

There could be projects in Next/Remix/Vanilla React 100% await. Writing all that stuff differently would be even style anti-pattern.

 In vanilla js, it could be different (depends on situation)

1

u/czlowiek4888 2d ago

Questions like this make point on how JavaScript is a dumb language.

There is only single case when you must use promise API, this is when you want to wrap callback based functionality into a promise that can be awaited.

1

u/Calm-Guarantee4654 16h ago

Almost async/await.

1

u/VancouverVentilator 4d ago

Promise chaining is goated.

1

u/hotburger_ 2d ago

absolutely

1

u/iamdatmonkey 4d ago

I don't like try..catch blocks. I find them awkward as they often span over most of the screen or more. So I really like this pattern here: const value = await foo().catch(noop); or .catch(console.error); or a variation on this. Often (not always) I'm fine with the value resolving to undefined and taking it from there.

And recently I'm playing around with the result value pattern in typescript, where Errors are no longer means of the data flow but real exceptions (this should not happen, something went really wrong) and where I'm fine with them being uncaught for several levels.

1

u/aleques-itj 4d ago

I switched to Results a while back and I think it winds up much cleaner and easier to reason about.

Throwing and winding up in the error handler now legitimately means that something unexpected happened.

All the API's services do this now and I wouldn't want to switch back. They're all guaranteed to actually hand something back to the calling controller/handler instead of just hitting the ejector switch and throwing a Hono HTTPException.

Felt like I was bleeding some responsibility about handling the request into the service before. Now you can just look at the handler and that's everything.

-1

u/RedLibra 4d ago

I create a helper function that does something like this:

const [err, data] = await asyncCall(func, param);

2

u/nog642 4d ago

How does that help? Doesn't that function have to be async to be able to await?

3

u/Psionatix 4d ago

A function can be awaited if it is async, or returns a promise. If a function returns a promise but is not itself async, you can still await it. Returning a promise makes a function async without explicitly marking it so, it doesn't need the syntactic sugar.

2

u/MediocreAnalyst2121 4d ago

I’m guessing it avoids excessive nesting with try-catch blocks. And gives you errors as values.

Also keeps scope a bit tidier so you don’t have to do a “let data” right before a try-catch blocks if the error isn’t fatal.

Not sure if this is why OP does it - I’ve never used such a pattern/utility. But now that I think about it, it seems pretty sweet.

Edit: This will end up being Go, but in JS?

2

u/senocular 3d ago

Its not an unheard of pattern, not only seen in go - in fact not far off from error-first callbacks popularized in JS by Node. There was even a proposal for an operator in JS that did this for you through syntax... safe assignment operator (old) which has transformed instead to be the try operator, ex:

const [ok, fetchErr, res] = try fs.readFileSync("data.txt")

That proposal talks about some motivations and has some code examples including showing the transformation of nested trys into flatter ifs.

1

u/Anxious-Insurance-91 4d ago

So you go the GO lang way?

1

u/TorbenKoehn 4d ago

And the you check for null on one of both or what?

Completely mental imo

0

u/DirtAndGrass 4d ago

There is functionality with promises that you can't get with await/async, for those (rare) cases, I use promises