Don't let the Try Catch Tower of Terror destroy your beautiful one liners.
npm install @bdsqqq/try
import{trytm}from"@bdsqqq/try";constmockPromise=()=>{returnnewPromise<string>((resolve,_)=>{setTimeout(()=>{resolve("hello from promise");},1000);});};constmockPromiseThatFails=()=>{returnnewPromise<string>((_,reject)=>{setTimeout(()=>{reject(newError("hello from promise"));},1000);});};const[data,error]=awaittrytm(mockPromise());const[data2,error2]=awaittrytm(mockPromiseThatFails());Async await feels like heaven because it avoids the callback hell or Pyramid of Doom by writing asyncronous code in a line by line format:
functionhell(){step1((a)=>{step2((b)=>{step3((c)=>{// ...})})})}asyncfunctionheaven(){consta=awaitstep1();constb=awaitstep2(a);constc=awaitstep3(b);// ...}Until error handling comes into play... Because then you end up with the Try-Catch Tower of Terror, where your beautiful one-liners magically expand to at least 5 lines of code:
asyncfunctionTerror(){leta;letb;letc;try{a=awaitstep1();}catch(error){handle(error);}try{b=awaitstep2(a);}catch(error){handle(error);}try{c=awaitstep3(b);}catch(error){handle(error);}// ...}An easy solution would be to append the .catch() method to the end of each promise:
asyncfunctioneasy(){consta=awaitstep1().catch(err=>handle(err));constb=awaitstep2(a).catch(err=>handle(err));constc=awaitstep3(b).catch(err=>handle(err));// ...}This approach solves the issue but can get a bit repetitive, another approach is to create a function that implements one Try Catch to replace all the others:
import{trytm}from"@bdsqqq/try"asyncfunctionawesome(){const[aData,aError]=awaittrytm(step1());if(aError)// ...const[bData,bError]=awaittrytm(step2(aData));if(bError)// ...const[cData,cError]=awaittrytm(step3(bData));if(cError)// ...// ...}I watched a fireship short and ended up in a rabbit hole to learn how to publish a NPM package. This is still an interesting pattern to use in your codebase but might be best copy pasted instead of being a dependency.
I'll leave the source code here so you don't have to look for the one .ts file in the /src folder:
exportconsttrytm=async<T>(promise: Promise<T>,): Promise<[T,null]|[null,Error]>=>{try{constdata=awaitpromise;return[data,null];}catch(throwable){if(throwableinstanceofError)return[null,throwable];throwthrowable;}};This code is blatantly stolen from a fireship youtube short, with minor additions to make data infer its typing from the promise passed as an argument.