0

I wanted to run different error handling with React Promise. API 1 and 2 should have different error handlings.

  1. Execute APIs all at once to save time.
  2. Run different error handling statements for each API as soon as possible, without waiting for the others.
  3. Each API should continue even if one fails.

How can this be done?

Reference:

Fetch API requesting multiple get requests

Promise.all([
            fetch(api1).then(value => value.json()),
            fetch(api2).then(value => value.json())
            ])
            .then((value) => {
               console.log(value)
              //json response
            })
            .catch((err) => {
                console.log(err);
            });
mattsmith5
  • 540
  • 4
  • 29
  • 67

2 Answers2

1

Promise.all is just wrapping up whatever promises you give it - so there's no reason you couldn't handle the errors separately for each one. For example, you could create a separate function for each of the fetches - you could even throw a custom error here that dictates some sort of "followUp" action to do, or identifies where the error is from, or anything (you can throw anything in javascript):

const fetchFromApi1 = async () => {
  try {
    const response = await fetch(api1);
    return response.json();

  } catch (err) {
    console.log('API 1 failed');
    
    // Throw a custom error
    throw {
      errorSource: 'API_CALL_1',
      message: 'API call 1 failed',
    };
  }
};

const fetchFromApi2 = async () => {
  // ----- 8< -----
};

Then you can just combine them in your your Promise.all - if you've thrown a custom error as above, you can use that to work out what to do:

const fetchAllTheThings = async () => {
  try {
    const [response1, response2] = await Promise.all([
      fetchFromApi1(),
      fetchFromApi2(),
    ]);

  } catch (err) {
    const { errorSource, message } = err;
    // do something....
  }
};

Edit

If you want to know which promise failed at the point of calling, you're probably better off using allSettled -

const fetchAllTheThings = async () => {
  const [result1, result2] = await Promise.allSettled([
    fetchFromApi1(),
    fetchFromApi2(),
  ]);

  if (result1.status === 'rejected') {
    // Sad for promise 1
  }

  if (result2.status === 'rejected') {
    // Sad for promise 2
  }
};
gerrod
  • 6,119
  • 6
  • 33
  • 45
  • on the final catch block, how do I differentiate between Error from API1 vs Error from API2? Our program will require different steps – mattsmith5 Nov 22 '22 at 00:48
  • @mattsmith5 - you're probably better off using `allSettled` - see edit – gerrod Nov 22 '22 at 01:05
  • See I want to handle all errors as they come in for each api, not when all the apis are completed , will all settled handle that? – mattsmith5 Nov 22 '22 at 02:45
  • No, `allSettled` will resolve when all the promises have settled (as the name implies ). You could always throw a custom `Error` in each `fetchFromApi...()` implementations, then inspect it in the outer-most error handler and work out what to do. Edits added above. – gerrod Nov 22 '22 at 03:34
  • "... each API should continue even if one fails." - the only way to do that would be use `allSettled`; `all` will fail as soon as one of the promises fails. You might need a bit of a combination of the approaches outlined above. – gerrod Nov 22 '22 at 03:47
0

const p1 = new Promise((res, rej) => {
  setTimeout(() => {
    res("p1 success")
  }, 1000)
})
const p2 = new Promise((res, rej) => {
  setTimeout(() => {
    res("p2 success")
  }, 3000)
})
const p3 = new Promise((res, rej) => {
  setTimeout(() => {
    rej("p3 failed")
  }, 1000)
})
const p4 = new Promise((res, rej) => {
  setTimeout(() => {
    rej("p4 failed")
  }, 2000)
})

Promise.allSettled([p1, p2, p3, p4])
  .then(console.log)
WestMountain
  • 136
  • 1
  • 1
  • 8