Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atomic async/await calls - is it possible to not execute first if second fails?

I'm asking on a bit of a whim as I'm no convinced this is possible to due the way time works, but was wondering if anyone had encountered a solution to this.

Would it be possible to make multiple async calls to different API endpoints that depend on each other atomic? In the sense that should one of them fail - none of them execute?

For example, if we needed to make 2 API requests, the first to POST a user and the second to make a POST using the ID returned from the first request. However, if I was unable to complete the second POST request - the user would not be created. Without this dependency I would default to using something such as Promise.all() however since I'm dependant on the result of the first call I don't think this would be the correct approach.

like image 440
shubwub Avatar asked Oct 20 '25 11:10

shubwub


1 Answers

Would it be possible to make multiple async calls to different API endpoints that depend on eachother atomic? In the sense that should one of them fail - none of them execute?

Yes, through a promise rejection.

Say you need to do two async operations sequentially (one after the other). You would do:

doA().then(doB);

If doA throws an error it rejects the promise and does doB does not get called. You can then catch the error and handle it in whatever way you might need. With async functions you would do:

(async function(){
  let a = await doA();
  let b = await doB(a);
})();

Which again, if doA throws an error then doB call does not happen.

You can make doA and doB throw different types of error to handle them differently (if needed, like for example... doing a rollback on A if B fails).

class DoAError extends Error { };
class DoBError extends Error { };

async function doA(){
   //...
   //... throw new DoAError();
   //...
}

async function doB(){
   //...
   //... throw new DoBError();
   //...
}

And then you just handle it like this:

(async function(){
  try {
    let a = await doA();
    let b = await doB(a);
  } catch(e){
    if(e instanceof DoAError){ /* something wrong with DoA */ }
    else if(e instanceof DoBError){ /* something wrong with DoB */ }
    else { throw e; }
  }
})();
like image 57
MinusFour Avatar answered Oct 22 '25 23:10

MinusFour