DEV Community

Cover image for Error Handling in JavaScript (Golang Style)
Bibek
Bibek

Posted on β€’ Originally published at blog.bibekkakati.me

69 14

Error Handling in JavaScript (Golang Style)

In this short article, we are going to see how we can handle error in JavaScript in Golang style.

I am assuming, you have some experience with JavaScript and you are aware of the issues with error handling like throwing an exception to the parent method from try-catch block or chaining multiple then-blocks and implementing logic inside it. These things can easily mess up with the code making it difficult to read.

Golang avoids these type of problems by handling errors/exceptions atomically.

Error handling in Golang



result, err := methodCall()
if err != nil {
  // handle error
}
// do something with the result


Enter fullscreen mode Exit fullscreen mode

We can use a similar pattern in JavaScript with the help of a try-catch block like this.



const getData = async () => {
  try {
    const result = await methodCall();
    return [result, null];
  } catch(error) {
    return [null, error];
  }
}


Enter fullscreen mode Exit fullscreen mode

If any error occurs, we are returning the error in the second position of the array and the result as null in the first position.

If there is no error, we are returning the result in the first position and error as null in the second position.

Now we can call the getData method then handle the result and error like this.



const [result, error] = await getData();
if (error !== null) {
  // handle the error
}
// do something with the result


Enter fullscreen mode Exit fullscreen mode

This pattern of error handling makes it very easy to read and understand the code.

Let me know what do you think about this pattern.


Originally published on blog.bibekkakati.me


Thank you for reading πŸ™

If you enjoyed this article or found it helpful, give it a thumbs-up πŸ‘

Feel free to connect πŸ‘‹

Twitter | Instagram | LinkedIn


If you like my work and want to support it, you can do it here. I will really appreciate it.



Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

While many AI coding tools operate as simple command-response systems, Qodo Gen 1.0 represents the next generation: autonomous, multi-step problem-solving agents that work alongside you.

Read full post β†’

Top comments (32)

Collapse
 
drumstickz64 profile image

You can actually turn this into a utility function, like so:

async function goCatch(promise) {
    try {
        const result = await promise
        return [result, null]
    } catch (err) {
        return [null, err]
    }
}
Enter fullscreen mode Exit fullscreen mode

You could also use an object like Brendan said.

Collapse
 
darkwiiplayer profile image
π’ŽWii πŸ³οΈβ€βš§οΈ β€’

I would wrap it in a higher order function though, something that takes an async function and returns a new async function with the added catch logic

Collapse
 
darkwiiplayer profile image
π’ŽWii πŸ³οΈβ€βš§οΈ β€’ β€’ Edited

Something like this, I guess:

const safe = fn => (*args) => fn(*args)
   .then(res => [res, null])
   .catch(err => [null, err])
Enter fullscreen mode Exit fullscreen mode
Collapse
 
bibekkakati profile image
Bibek β€’

Yeah. That can be way of implementing it.

Collapse
 
bibekkakati profile image
Bibek β€’ β€’ Edited

Yeah. Utility function can be very helpful.

Collapse
 
calinzbaenen profile image
Calin Baenen β€’

Better yet, just use GoLang.

Collapse
 
bibekkakati profile image
Bibek β€’

Good idea. πŸ˜‰

Collapse
 
calinzbaenen profile image
Calin Baenen β€’ β€’ Edited

Of course it is! Everyone knows Go is the best language objectively.

Collapse
 
calinzbaenen profile image
Calin Baenen β€’

I've reconsidered. . .

Collapse
 
calinzbaenen profile image
Calin Baenen β€’

Thinking back, I spoke very unwise words.
It should be "Better yet, just use Rust." β€” Rust's error handling is exceptional. :ΓΎ

Collapse
 
arndissler profile image
Arnd Issler β€’

The thing is: a good bunch of developers is not prepared to "just use" Rust. The learning curve for Rust is the same as its error handling: exceptional.

But once learned and added to your developer toolchain, it is unlikely that you come back to this article in 2028 and push the next programming language, as you might have learned on the way that not every programming language is suitable for all use cases.

Collapse
 
douglascalora profile image
DouglasCalora β€’ β€’ Edited
import { Loading, Notify } from 'quasar'

/**
 * @param {Promise} promise
 * @param {object} config={notifySuccess, notifyError, useLoading}
 * @example promiseHandle(new Promise(), { notifyError: { message: 'Erro' }, notifySuccess: { message: 'Sucesso' } })
 */
export default async function (promise, config = {}) {
  const {
    notifySuccess = {},
    notifyError = {},
    useLoading = false,
    onLoading
  } = config

  onLoading && onLoading(true)
  useLoading && Loading.show()

  const primiseToBeExec = typeof promise === 'function' ? promise() : promise
  const hasNotify = notify => Object.keys(notify).length

  try {
    const data = await (Array.isArray(promise) ? Promise.all(promise) : primiseToBeExec)
    hasNotify(notifySuccess) && Notify.create({ type: 'success', ...notifySuccess })
    return { data, error: null }
  } catch (error) {
    hasNotify(notifyError) && Notify.create({ type: 'error', ...notifyError })
    return { data: null, error }
  } finally {
    onLoading && onLoading(false)
    Loading.hide()
  }
}
Enter fullscreen mode Exit fullscreen mode

I added a callback onLoading so I can do somenthing while function is running.

const { data, error } = await promiseHandler(callbackFn, { onLoading: value => console.log('is loading?', value) })

Collapse
 
bibekkakati profile image
Bibek β€’

πŸ‘¨πŸΌβ€πŸ’»

Collapse
 
jsnanigans profile image
Brendan Mullins β€’

Nice, but I would personally use an object instead of the array as a return type

Collapse
 
bibekkakati profile image
Bibek β€’

I prefer array because if we use object, destructuring will be an issue if there is more than one block in same level. Also we need to be aware of the property name.

Collapse
 
jankapunkt profile image
Jan KΓΌster πŸ”₯ β€’

Property name can be set by convention across your whole project. Let's say { error, result } which is to me most verbose and would not lead to accidental access compared to array indices

Thread Thread
 
bibekkakati profile image
Bibek β€’

Yeah, that is right. But in case of multiple blocks in the same scope it can create issue, as you will not be able de-structure it like this

const {error, result} = await method();

// second method call will create an issue
const {error, result} = await method2();
Enter fullscreen mode Exit fullscreen mode

But in case of array, you can use other variable name in the second method call.

Feel free to correct me, if I am missing something.

Thread Thread
 
jsnanigans profile image
Brendan Mullins β€’

a few ways you could avoid this:

const responseOne = await methodOne();
if (responseOne.error) return

const responseTwo = await methodTwo();
if (responseTwo.error) return

// of if you want destructuring
const {error: methodOneError, result: resultOne} = await methodOne();
if (methodOneError) return
const {error: methodTwoError, result: restultTwo} = await methodTwo();
if (methodTwoError) return
Enter fullscreen mode Exit fullscreen mode

Im not saying the array descructuring is worse, its just a prefference

Thread Thread
 
erikhofer profile image
Erik Hofer β€’

You can rename the variable when destructuring an object.

const {error, result} = await method();

const {error: error2, result: result2} = await method2();
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
bibekkakati profile image
Bibek β€’

@jsnanigans Yeah, It's just a preference.

Thread Thread
 
bibekkakati profile image
Bibek β€’ β€’ Edited

@erikhofer I am aware of that.

Collapse
 
grzegorzbielski profile image
Grzegorz Bielski β€’

I'm not a huge fan of this pattern.
The idea of explicitly returning errors rather than throwing unchecked errors is great, but the proposed implementation is flawed - we need to always check the elements of the tuple before using the value to see if there is an error which will become error-prone rather quickly.
Fortunately, this is an already solved problem, known in other langues as Either or Result type, in which all of these ifs are abstracted away in form of map and flatMap / chain operations.
Potential implementation: gigobyte.github.io/purify/adts/Eit...

Collapse
 
bibekkakati profile image
Bibek β€’

Got your point. After all it's all about own preference.

Collapse
 
chinmaykb profile image
Chinmay Kabi β€’

I saw this in a Fireship video, ditto πŸ‘€

Collapse
 
bibekkakati profile image
Bibek β€’

Is it? Need to check it.

I saw this in a 3 years old article.

Collapse
 
njavilas2015 profile image
njavilas2015 β€’ β€’ Edited

in typescript

async function goCatch<T>(promise: Promise<T>): Promise<[T | null, null | Error]> {
    try {

        const result: Awaited<T> = await promise

        return [result, null]

    } catch (err) { return [null, err] }
}


const main = async (params: params) => {


    const [store, err] = await goCatch(qbpbspfzfeyudz.create(params.store))

}

Enter fullscreen mode Exit fullscreen mode
Collapse
 
outthislife profile image
Talasan Nicholson β€’

Can just do if (error) though.

Collapse
 
bibekkakati profile image
Bibek β€’

Yeah, we can do that. Sometimes I just like to check explicitly.

Collapse
 
clsource profile image
Camilo β€’

Nice idea. Thanks for sharing :)

Collapse
 
bibekkakati profile image
Bibek β€’

I'm glad that you liked it. 😊

Collapse
 
bibekkakati profile image
Bibek β€’

Got it. Thank you for sharing that.

nextjs tutorial video

Youtube Tutorial Series πŸ“Ί

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series πŸ‘€

Watch the Youtube series

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay