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

Time:09-22

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.

CodePudding user response:

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; }
  }
})();

CodePudding user response:

You don't need to do anything special to handle this case. Try this:

  1. Set flags to determine if each API completes,
  2. Run an endfunc() at the end of each API-calling function,
  3. Only proceed with endcall()'s logic if each flag is set.

Set the flags...

var api1 = api2 = false;

Define your API-calling functions...

apicall1() {
    // do api call
    api1 = true;
    endfunc();
}

apicall2() {
    // do another api call
    api2 = true;
    endfunc();
}

And finish it all off with a...

endfunc() {
    if(api1 !== true && api2 !== true) {
        return;
    }
    // stuff to execute only after all API calls are done
}`
  • Related