0

This code is ugly, isn't it?

import axios from 'axios';

async function f1() {
  try {
    const resp = await axios.get('http://www.randomnumberapi.com/api/v1.0/randomnumber');
    return resp.data[0];
  } catch (err) {
    throw err;
  }
}

async function f2() {
  try {
    return 1 + (await f1());
  } catch (err) {
    throw err;
  }
}
async function main() {
  try {
    return 1 + (await f2());
  } catch (err) {
    throw err;
  }
}

try {
  console.log(await main());
} catch (err) {
  throw err;
}

But it seems, I have no way to write it in a different way. Because each await requires the try...catch. Otherwise I have the Unhandled promise rejection error. But too many try...catchs make the code not so nice.

Is there an approach how to make this code like nicer?

Note 1: I'm using Nest.js if it helps for the good answer. Note 2: I've looked at such answers, but they are slightly about different: How to avoid using try...catch blocks Removing excessive try-catch blocks Too many try/catch blocks. Is this proper? bad try catch block design? Try catch block in express

Vova
  • 1
  • 1

2 Answers2

0

The question is not very clear but I'll try to answer it in the best possible way. For the pattern above, if you just want to return err in each one, you can have something like

    import axios from 'axios';
    
    async function f1() {
      const resp = await axios.get('http://www.randomnumberapi.com/api/v1.0/randomnumber');
      return resp.data[0];
    }
    
    async function f2() {
      return 1 + (await f1());
    }
    
    async function main() {
      return 1 + (await f2());
    }
    
    const data = await main().catch(err =>console.log(`Had Error in catch. ${err}`))
    console.log(data);
  1. If you have different implementation in each function of the error, you can have the syntax of .then and .catch there like above in each one.

  2. If you are using NestJS you can take advantage of Exception Filters to get the context where error occur and handle it easily.

  3. Not exactly but you can use a higher order function to get error handling as well.

    import axios from 'axios';
    
    async function ErrorHandler(errResolve, task, ...args) {
      try {
        const res = await task(args);
        // Call any filtering or data manipulation here
        return res
      } catch(e) {
        return errResolve(e);
      }
    }
    
    async function f1() {
      const resp = await axios.get('http://www.randomnumberapi.com/api/v1.0/randomnumber');
      return resp.data[0];
    }
    
    async function f2() {
      return 1 + (await f1());
    }
    
    async function main() {
      return 1 + (await f2());
    }
    
    const res = await ErrorHandler(err => console.log(`Had Error. ${err}`), main)
    console.log(res);
    

What to use will depend on the use case. The one mentioned above can be cleaned by a lot of ways. Using TS class and filters, the code can be cleaned more. Moreover you can also write custom exception filters too but that might be an overkill. If you can explain your use case more then it be more helpful.

Shobhit Tewari
  • 535
  • 5
  • 20
  • Thanks! I see for now two solutions. 1) Use tailed .catch(): `let result = await f1().catch( err=>console.log(err))` 2) Use `try...catch` just in one place on the lowest level (let an error bubble up while an interceptor will catch it). – Vova Apr 14 '23 at 05:54
  • For the use case you demonstrated above, I found these good. – Shobhit Tewari Apr 14 '23 at 10:49
0

The main issue with your example that I see is not related to your specific technology. The thing is that you catch an exception/error just to rethrow it as is without doing something specific related to the exception or without enriching the information of the occurred error with more helpful details for the next layer.

As a rule of thumb I usually only catch exceptions at places where I am able to deal with that error or at least add more information to throw it up to the next higher level. For instance, with more informational parameters, a more specific message. Or throw it as a custom exception/error type. Or replace it with returning error information or notifications instead (see also https://martinfowler.com/articles/replaceThrowWithNotification.html)

Just catching and rethrowing as is does not add value and just makes the code more complex and less readable as your gut feeling already told you. If you can't do anything useful with an exception (as described above) rather let it bubble up to some other place where it can be dealt with.

Andreas Hütter
  • 3,288
  • 1
  • 11
  • 19