Home > Mobile >  Promise not completing on rejection
Promise not completing on rejection

Time:04-06

So I have a form that submits with the following function:

const formSubmit = async (formData) => {
  const response = await SubmissionsResource.create(formData)
  const { data, status } = response
  console.log('Request completed.')
  if (status === 201) {
    toast.success('Submission created.')
  } else {
    toast.error('Something went wrong.')
    console.error(data)
  }
}

Which uses the following:

const SubmissionsResource = {
  create: ({ formData }) => (
    Request.privatePost(apiUrl('submissions'), formData)
  ),
}

Which uses the following:

export const Request = {
  privateRequest: ({ data, method, params, url }) => {
    axios.interceptors.request.use((request) => {
      request.headers.authorization = getBearerToken()
      return request
    }, (error) => Promise.reject(error))

    axios.interceptors.response.use(
      (response) => response,
      async (error) => {
        const originalRequest = error.config

        // If request is coming from a sign in attempt
        if (error.response.status === 401 && originalRequest.url.includes('auth/token')) {
          return Promise.reject(error)
        }

        // If request is coming from elsewhere, assume token might be expired
        if (error.response.status === 401 && !originalRequest._retry) {
          originalRequest._retry = true
          const refresh_token = LocalStorageService.getRefreshToken()
          const response = await axios.post(
            `${API_BASE}/oauth/token`,
            { client_id, client_secret, grant_type: 'refresh_token', refresh_token }
          )
          if (response.status === 200) {
            LocalStorageService.setUser(response.data)
            axios.defaults.headers.common.Authorization = getBearerToken()
            return axios(originalRequest)
          }
          return Promise.reject(error)
        }
        return Promise.reject(error)
      }
    )
    return axios({ method, url, data, params })
  },
  privatePost: (url, data) => (
    Request.privateRequest({ method: 'post', data, url })
  )
}

When the response is successful, I always see the "Request completed" log, and I see the toast.success message. However, when the request fails, I never see the "Request completed" log, nor the toast.error message.

The axios interceptor should retry once if the response comes back unauthorized (401 status code), which it successfully does, and in all other cases, reject the promise and return the error.

Request.privateRequest should reject the promise and return the error to Request.privatePost, which should return back to SubmissionsResource.create, and then finally to formSubmit. However, instead of completing the promise and returning an error, it just halts the entire function and doesn't ever get to the "Request completed" log.

I'm assuming this is due to an incorrect understanding with promises on my end, but I can't figure out what that is. Why isn't the promise being completed and continuing on to the next line within formSubmit?

CodePudding user response:

By returning Promise.reject(), you're telling axios to reject the promise returned by the network request, but the calling code doesn't catch any rejection.

Try try-ing:

const formSubmit = async (formData) => {
  try {
    const response = await SubmissionsResource.create(formData)
    const { data, status } = response
    console.log('Request completed.');
    toast.success('Submission created.')
  } catch(error) {
    if (error.response.status === 401)
      toast.error('Bad news: 401.');
    else 
      toast.error('Some other kind of bad news.');
  }
}
  • Related