Search code examples
javascriptnode.jsreactjsasync-awaitnested-if

Am I over-nesting in JavaScript Async/Await


I am developing a React App (This is not important, because what I am going to explain can happen in other situations as well.)

I have three asynchronous functions, let's call them func1 and func2, and func3 and this is how they look. This is the general pattern of these functions.

const func1 = async ()=>{
    try {
        // do something
        const resultForFunc2 = // the end result of doing something that is going to be used in func2
        return {statusCode: 200, body: resultForFunc2, error: null}
    } catch(err) {
        console.log("Error in executing func1", err)
        return {statusCode: 400, body: null, error: err}
    }
}

Now the way these functions are called is that func1 returns a value that is used in func2 and func2 returns a value that is used in func3.

So this is how I call them:

const all = async () => {
  const response1 = await func1();
  if (response.statusCode === 200) {
      const response2 = await func2(response1);
      if (response2.statusCode === 200) {
          const response3 = await func3(response2);
          if (response3.statusCode === 200) {
              return { statusCode: 200, body: response3.body, error: null };
          } else {
              return { statusCode: 400, error: response3.error, body: null };
          }
      } else {
        return { statusCode: 400, error: response2.error, body: null };
      } 
  } else {
      return { statusCode: 400, error: response.error, body: null };
  }
}
 

This works for me because I call the above all function in a React component, in a useEffect() for example, and whenever I get a 400 statusCode I set an error state variable to true and then display an error screen (I came up with this idea, so feel free to criticize it, I appreciate it actually). But the bad thing is that I have so many nested ifs that make the code ugly, dirty, and hard to read and debug. Does anyone have an idea how I can get the benefits of the above code block, without using nested ifs. Thank you.


Solution

  • This might be a good question for code review

    I have two ideas for reducing nesting. One is using a catch function instead of try catch blocks, i.e.

    const err = e => console.error(e);
    
    const func1 = async () => {
        // do something
        const resultForFunc2 = // the end result of doing something that is going to be used in func2
        return {statusCode: 200, body: resultForFunc2, error: null}
    }
    
    const result1 = await func1.catch(err);
    

    Another idea is to exit on a fail instead of nest the continuing code inside a block. i.e.

    const all = async () => {
      const response1 = await func1().catch(err);
      if (response.statusCode !== 200) return { statusCode: 400, error: response.error, body: null };
      const response2 = await func2().catch(err);
      if (response2.statusCode !== 200) return { statusCode: 400, error: response2.error, body: null };
      //and so on
    }