Search code examples
javascriptnode.jses6-promise

Promise.allSettled returns catch as fullfilled


I am making https requests using a function batchRequest that collects the promises in batches with Promise.allSettled and sends them to the apiRequest function that makes the actual calls with axios.

On the batchRequest function I send an array of urls to the HTTP request function and await the results. Then I use the Promise.allSettled status to identify the rejected ones. But when the apiRequest catches as error Promise.allSettled sees it as status: fullfilled

async function batchRequest(data, index) {
  console.log(`Running... ${index} round`)
  while (data.length) {

    // Batched request according to concurrent setting
    const batch = data
      .splice(0, settings.concurrent)
      .map((url) => apiRequest(url, index))

    const results = await Promise.allSettled(batch)

    results.forEach(({ status, value, reason }) => {
      if (status === 'fulfilled') {
        console.log(value) // I get both the try and catch here from `apiRequest`
      }
      if (status === 'rejected') {
        console.log(reason)
        // I never get anything here
      }
    })
  }
}

Api request function

async function apiRequest(url, index) {
  try {
    const { data } = await axios('https://api-end-point')
    return 'All good' + url
  } catch (error) {
    const status = error.response?.status ?? 'No response'
    return  `Error: ${status}, ${url}`
  }
}

Solution

  • Don't return the error. throw it!

    async function apiRequest(url, index) {
      try {
        const { data } = await axios('https://api-end-point')
        return 'All good' + url
      } catch (error) {
        const status = error.response?.status ?? 'No response'
        throw  `Error: ${status}, ${url}` // <------------change here
      }
    }