Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using async/await and try/catch to make tiered api calls

SO friends!

I need to make a call to an api; if it fails, I need to make a call to same api with different param; if it fails AGAIN, I need to make a call to same api with a third, different param; if it fails finally after that, is an actual error and can bugger out.

Only way I can figure to do this is with nested try/catch statements, ala:

const identityCheck = async (slug) => {
  let res;
  try {
    res = await Bundle.sdk.find(slug);
  } catch (err) {
    console.log('Fragment didn\'t work ========', slug, err);

    try {
      res = await Bundle.sdk.find(`package/${slug}`);
    } catch (e) {
      console.log('Fragment didn\'t work package ========', e);

      try {
        res = await Bundle.sdk.find(`${slug}-list`);
      } catch (error) {
        console.log('None of the fragments worked================.', error);
      }
    }
  }

  return logResponse(res);
};

identityCheck('fashion');

But seems like there MUST be another simpler way to do this. I tried boiling down into a retry function, but that just ends up being even more code and way less clear:

const identityCheck = (slug) => {
  const toTry = [
    slug,
    `package/${slug}`,
    `${slug}-list`
  ];

  return new Promise((resolve, reject) => {
    let res;
    let tryValIndex = 0;

    const attempt = async () => {
      try {
        res = await Bundle.sdk.find(toTry[tryValIndex]);
        return resolve(logResponse(res));
      } catch (err) {
        console.log(`toTry ${toTry[tryValIndex]} did not work ========`, slug, err);

        if (tryValIndex >= toTry.length) {
          return reject(new Error('Everything is broken forever.'));
        }

        tryValIndex++;
        attempt();
      }
    };

    attempt();
  });
};

Guidance and opinions appreciated!

like image 941
megkadams Avatar asked Oct 29 '25 05:10

megkadams


1 Answers

Avoid the Promise constructor antipattern, and use a parameter instead of the outer-scope variable for the recursion count:

function identityCheck(slug) {
  const toTry = [
    slug,
    `package/${slug}`,
    `${slug}-list`
  ];
  async function attempt(tryIndex) {
    try {
      return await Bundle.sdk.find(toTry[tryIndex]);
    } catch (err) {
      console.log(`toTry ${toTry[tryIndex]} did not work ========`, slug, err);
      if (tryIndex >= toTry.length) {
        throw new Error('Everything is broken forever.'));
      } else {
        return attempt(tryIndex+1);
      }
    }
  }
  return attempt(0);
}
like image 115
Bergi Avatar answered Oct 31 '25 18:10

Bergi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!