1

I'm processing multiple records using Promise.all now if any error occurs I want to capture individual record in catch statement

I have written a method callApi now I'm calling callApi method in main code

try {
 let result = await callApi(res)
}
catch (err) {

}

async function callApi(records) {
  return Promise.all(
    records.map(async record => {
        await processRecord(record)
    })
  )
}

I want to display/capture individual record in catch block if any error occurs ex below

try {
 let result = await callApi(res)
}
catch (err) {
 console.log('Got error while processing this record', record)
}

But how I will get record variable in catch block

Dev
  • 413
  • 10
  • 27

1 Answers1

1

Since it's processRecord that may throw, if you want the record it's processing to be what is caught, rather than the actual error, catch the processRecord error, and throw the record:

function callApi(records) {
  return Promise.all(
    records.map(record => (
      processRecord(record)
        .catch((err) => {
          throw record;
        })
    ))
  )
}

It may be useful to return both the record and the error when catching, though:

try {
  let result = await callApi(res)
} catch ({ err, record }) { // <--------
  console.log('Got error while processing this record', record);
  console.log(err);
}

function callApi(records) {
  return Promise.all(
    records.map(record => (
      processRecord(record)
        .catch((err) => {
          throw { err, record };
        })
    ))
  )
}

Note that because callApi already explicitly returns a Promise, there's no need to make it an async function.

To wait for all requests to finish, and then check the errors on each, do something like:

function callApi(records) {
  return Promise.all(
    records.map(record => (
      processRecord(record)
        .then(value => ({ status: 'fulfilled', value }))
        .catch(err => ({ status: 'rejected', reason: { record, err } }))
    ))
  );
}

const result = await callApi(res);
const failures = result.filter(({ status }) => status === 'rejected');
failures.forEach(({ reason: { record, err } }) => {
  // record failed for reason err
});
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Interestingly it's not capturing error in catch block if I print result in in try block it's giving all errors and records. – Dev May 24 '19 at 05:47
  • Oops, that's right, have to actually `throw` for it to be caught in the outer `catch` – CertainPerformance May 24 '19 at 05:49
  • Got it, what if I want print all error records in catch block , it's giving single error record because if error happens it's throwing immediately. – Dev May 24 '19 at 06:08
  • 1
    Use something like [Promise.allSettled](https://stackoverflow.com/questions/31424561/wait-until-all-es6-promises-complete-even-rejected-promises), then filter by the ones with errors – CertainPerformance May 24 '19 at 06:10
  • Can you provide above code with Promise.allSettled – Dev May 24 '19 at 08:58
  • Ok, see edit (`Promise.allSettled` isn't actually in the spec yet, it's just a proposal) – CertainPerformance May 24 '19 at 09:12