DEV Community

loading...

Migrating from promise chains to async-await and escaping the try catch hell

AvishkarDalvi
・2 min read
async ()=> {
await promise
}
Enter fullscreen mode Exit fullscreen mode

async-await is a life saver when it comes to avoiding callback hell or the pyramid of doom.

function hell(){
step1((a)=>{
  step2((b)=>{
    step3((c)=>{
       // some code ...
         })
       })
     })
}
Enter fullscreen mode Exit fullscreen mode

The above code can be written in a clean line-by-line format using async-await.

async function heaven(){
   const a= await step1();
   const b= await step2(a);
   const c= await step3(b);
   return a + b + c;
}
Enter fullscreen mode Exit fullscreen mode

This is great but when it comes to error handling this simplicity again goes for a toss because you end up with a try-catch tower of terror.

async function towerOfTerror(){
let a;
let b;
let c;

try{
 a=await step1();
} catch(error){
 handle(error);
}

try{
 b=await step2(a);
} catch(error){
 handle(error);
}

try{
 c=await step3(b);
} catch(error){
 handle(error);
}

return a + b + c;
}
Enter fullscreen mode Exit fullscreen mode

All your one-liners have now expanded to at least 5 lines of code.
One easy way out would be to append the catch method to the end of each promise.

await step1().catch(fun);
Enter fullscreen mode Exit fullscreen mode

But that can still get repetitive.

async function getBetter(){
   const a= await step1().catch(err=>handler(err);
   const b= await step2(a).catch(err=>handler(err);
   const c= await step3(b).catch(err=>handler(err);
   return a + b + c;
}
Enter fullscreen mode Exit fullscreen mode

Another option is to create a function that implements one try-catch to replace all the others. It will first resolve the promise and then return an array that has the first element as the data and the second element as an error. But if there is an error then the data is null and the error is defined.

async function awesome(){
 try{
  const data=await promise;
  return [data,null];
 } catch(error){
  console.error(error);
  return [null,error];
 }
Enter fullscreen mode Exit fullscreen mode

Now you can call this function in your code you can de-structure it to get a clean one-liner error handling.

async function main(){
 const[data,error]=await awesome();
 const[data2,error2]=await awesome();
//or use the if statement if you want to handle the error differently
if(error){
   //do something
   }
}
Enter fullscreen mode Exit fullscreen mode

Discussion (4)

Collapse
miketalbot profile image
Mike Talbot • Edited

Given your result requires a, b and c and would fail without all of them, why not write one catch handler?

async function heaven(){
   try {
      const a= await step1();
      const b= await step2(a);
      const c= await step3(b);
      return a + b + c;
   } catch(e) {
       // something like
       // throw new Error("Trouble in heaven")
       // or
       return 0
   }
}
Enter fullscreen mode Exit fullscreen mode

Also your awesome function is probably missing the promise parameter

Collapse
kalashin1 profile image
Kinanee Samson

i have been looking for this all over, thanks man

Collapse
avishkardalvi profile image
AvishkarDalvi Author

I am glad you found this helpful. Thanks for the feedback.

Collapse
abel_soares profile image
Abel Soares

I don’t think this brings any advantage, if you handle errors equally, then just handle it in one try catch. If you handle errors differently, then your solution will have a if hell