Axios handling errors

494,561

Solution 1

Actually, it's not possible with axios as of now. The status codes which falls in the range of 2xx only, can be caught in .then().

A conventional approach is to catch errors in the catch() block like below:

axios.get('/api/xyz/abcd')
  .catch(function (error) {
    if (error.response) {
      // Request made and server responded
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
    } else if (error.request) {
      // The request was made but no response was received
      console.log(error.request);
    } else {
      // Something happened in setting up the request that triggered an Error
      console.log('Error', error.message);
    }

  });

Another approach can be intercepting requests or responses before they are handled by then or catch.

axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });

Solution 2

If you want to gain access to the whole the error body, do it as shown below:

 async function login(reqBody) {
  try {
    let res = await Axios({
      method: 'post',
      url: 'https://myApi.com/path/to/endpoint',
      data: reqBody
    });

    let data = res.data;
    return data;
  } catch (error) {
    console.log(error.response); // this is the main part. Use the response property from the error object

    return error.response;
  }

}

Solution 3

You can go like this: error.response.data
In my case, I got error property from backend. So, I used error.response.data.error

My code:

axios
  .get(`${API_BASE_URL}/students`)
  .then(response => {
     return response.data
  })
  .then(data => {
     console.log(data)
  })
  .catch(error => {
     console.log(error.response.data.error)
  })

Solution 4

If you wan't to use async await try

export const post = async ( link,data ) => {
const option = {
    method: 'post',
    url: `${URL}${link}`,
    validateStatus: function (status) {
        return status >= 200 && status < 300; // default
      },
    data
};

try {
    const response = await axios(option);
} catch (error) {
    const { response } = error;
    const { request, ...errorObject } = response; // take everything but 'request'
    console.log(errorObject);
}

Solution 5

I tried using the try{}catch{} method but it did not work for me. However, when I switched to using .then(...).catch(...), the AxiosError is caught correctly that I can play around with. When I try the former when putting a breakpoint, it does not allow me to see the AxiosError and instead, says to me that the caught error is undefined, which is also what eventually gets displayed in the UI.

Not sure why this happens I find it very trivial. Either way due to this, I suggest using the conventional .then(...).catch(...) method mentioned above to avoid throwing undefined errors to the user.

Share:
494,561

Related videos on Youtube

mignz
Author by

mignz

Updated on July 17, 2022

Comments

  • mignz
    mignz almost 2 years

    I'm trying to understand javascript promises better with Axios. What I pretend is to handle all errors in Request.js and only call the request function from anywhere without having to use catch().

    In this example, the response to the request will be 400 with an error message in JSON.

    This is the error I'm getting:

    Uncaught (in promise) Error: Request failed with status code 400

    The only solution I find is to add .catch(() => {}) in Somewhere.js but I'm trying to avoid having to do that. Is it possible?

    Here's the code:

    Request.js

    export function request(method, uri, body, headers) {
      let config = {
        method: method.toLowerCase(),
        url: uri,
        baseURL: API_URL,
        headers: { 'Authorization': 'Bearer ' + getToken() },
        validateStatus: function (status) {
          return status >= 200 && status < 400
        }
      }
    
      ...
    
      return axios(config).then(
        function (response) {
          return response.data
        }
      ).catch(
        function (error) {
          console.log('Show error notification!')
          return Promise.reject(error)
        }
      )
    }
    

    Somewhere.js

    export default class Somewhere extends React.Component {
    
      ...
    
      callSomeRequest() {
        request('DELETE', '/some/request').then(
          () => {
            console.log('Request successful!')
          }
        )
      }
    
      ...
    
    }
    
    • Niyoko
      Niyoko about 6 years
      Do you want to break the promise chain?
    • mignz
      mignz about 6 years
      Not sure. Does that stop me from having to use catch when I call the request function?
    • Benjamin Gruenbaum
      Benjamin Gruenbaum about 6 years
      Is an unsuccessful status code logically an exceptional state in your application? How would you expect calling code to react to it?
    • Roamer-1888
      Roamer-1888 about 6 years
      If you send errors down the success path, you will, in all probability, need to test for them in order to branch at some higher level. I'd say allow success to be success and errors to be errors, and .catch() accordingly.
  • airtonix
    airtonix almost 4 years
    Sorry to nitpick, but two things: if you really want to use async move it down in front of your promise resolve/reject function. Or ideally, don't even bother using the promise (since you're wrapping the baseRequest in an async decorator) and just continue with your try/catch and error type branching and just use return instead of resolve. Secondly, I like that test for absent server responses! But when axios times out, will it throw an exception and be treated as if the server didn't return a response? or are these scenarios the same thing?
  • David Schumann
    David Schumann almost 4 years
    Thanks for the suggestion airtonix. This function was pretty old and I am always happy to improve code. The mix of async/await and Promises in this function is not ideal. Can you edit my comment to reflect those changes? RE your question AFAIK axios treats both in the catch portion of the code. I would manually set the timeout to be very low to test my error handling of timeouts. By "Absent server" you mean 404 errors? Or no-internet errors? All handled in the catch block, so try triggering them yourself to test.
  • winklerrr
    winklerrr over 3 years
    Why do you just use simple returns in your then parts and Promise.reject in your catch parts? Doesn't seem really consistent to me.
  • Plabon Dutta
    Plabon Dutta over 3 years
    I used the snippet from official axios documentation on github. github.com/axios/axios#interceptors
  • Plabon Dutta
    Plabon Dutta over 3 years
    Anyway, I think you're referring to the interceptor part, but there is no then there. Requests or responses are being intercepted before being handled and thus, we do not want to Promise.resolve() yet. However, if an error is encountered, we can Promise.reject() if we want to. Or, we can return something and later when the request or response will be handled, we can use Promise.reject(). Same thing.
  • winklerrr
    winklerrr over 3 years
    Ah yes, that makes sense! So in the error case we already know, that the request doesn't need to be handled further and therefore the promise can already be rejected.
  • Plabon Dutta
    Plabon Dutta over 3 years
    That's exactly what's happening here. :)
  • Anuj Raghuvanshi
    Anuj Raghuvanshi over 3 years
    Try error.response . Hope all are looking for this. It will give proper error details returned by server.
  • Despertaweb
    Despertaweb about 3 years
    It happens the very same to me today :/
  • SijuMathew
    SijuMathew almost 3 years
    I have seen the error.response being undefined and then it will fail in the destructuring
  • BankBuilder
    BankBuilder almost 3 years
    try..catch only works with async/await. You can either handle it using .catch() (catch rejected promise) or try { await axios... } catch (err) {...} (catch exception resulting from rejected promise)
  • Hidayt Rahman
    Hidayt Rahman over 2 years
    Thanks, Man!. I was not aware about the error key has also the error.request
  • Admin
    Admin over 2 years
    this really solved my problem, thanks elonaire
  • 12kb
    12kb over 2 years
    Won't it cause a memory leak? UX would also be "strange". Endless spinner instead of clear error message in right place on the page. Guess that's not what makes users happy. My vote for adding honest error handler in each place where you do a request!)
  • Normal
    Normal almost 2 years
    .catch(error) { if (error.response) ... } axios always returns error.response and error.request, so I'm not sure if this worked with any of you correctly, but it did not work for me, even though this approach is mentioned in the docs
  • Normal
    Normal almost 2 years
    it's catch(error) { ... } and not catch(function(error) { ... } ) where did you bring that from?