Murakami
Murakami

Reputation: 3760

Handling error from async await syntax with axios

Here's my chunk of code:

  const getToken = async () => {
    try {
      const token = await axios.post(keys.sessionURL, {
        email: keys.verificationEmail,
        password: keys.verificationPassword,
      });
    } catch (err) {
      throw new Error('Unable to establish a login session.'); // here I'd like to send the error to the user instead
    }
  };

So as you can see I'm connecting to external server in order to get a token. And that works. Now, I'd like to catch an error but this time not with 'throw new error' but I'd like to send it to the user, so I'd like to have something like this instead:

res.status(401).send('Unable to get a token');

But because I'm not inside the route handler I cannot use 'res'. How can I send it to the user then?

Thank you!

Upvotes: 59

Views: 120590

Answers (8)

user21031741
user21031741

Reputation: 1

const getPass = (e) => {
    e.preventDefault()
    const post = { userName: userName } 
        axios.post("/", post)    //axios.post(keys.sessionURL, {email: keys.verificationEmail,password: keys.verificationPassword,})
        .then(res => {
            if(!res.ok){
                throw Error('Network Error'); //error from axios
            }
            return res.json(); 
        }).catch(err => {
            console.log(err.message) //to display the error to your user just use the useState to define your error
            })
  }

const getPass = (e) => {
    e.preventDefault()
    const post = { userName: userName } 
        axios.post("/", post)    //axios.post(keys.sessionURL, {email: keys.verificationEmail,password: keys.verificationPassword,})
        .then(res => {
            if(!res.ok){
                throw Error('Network Error'); //error from axios
            }
            return res.json(); 
        }).catch(err => {
            console.log(err.message) //to display the error to your user just use the useState to define your error
            })
  }

Upvotes: -1

Akshay Seth
Akshay Seth

Reputation: 1272

For axios version-0.19.0 below code worked after hours of struggling with async await.Not sure about other versions though!

catch(error){
console.log(error.response.data.error)
}

Upvotes: 68

Daniel Danielecki
Daniel Danielecki

Reputation: 10502

Elegant & with TypeScript.

import axios, { AxiosResponse, AxiosError } from "axios";
...

const response: void | AxiosResponse<any, any> = await axios({
  headers: {
    Authorization: `Bearer ${XYZ}`,
    Accept: "application/json",
  },
  method: "GET",
  params: {
    ...
  },
  url: "https://api.abcd.com/...",
}).catch((error: AxiosError) => {
  if (error instanceof Error) {
    console.error(
      "Error with fetching ..., details: ",
      error
    );
  }
});

Upvotes: 3

Dreamoon
Dreamoon

Reputation: 468

Keep the grace of async / await :

const result = await axios.post('/url', params)
    .catch((err) => {
       // deal with err, such as toggle loading state, recover click and scroll.
       this.loading = false;
       // recover the reject state before.
       return Promise.reject(err);
    });

this.data = result; // not exec when reject

Upvotes: 9

Pawel Cioch
Pawel Cioch

Reputation: 3184

try/catch is not a good solution. It's meant to catch runtime error, not HTTP error coming from axios if error is processed by interceptor and then passed back to caller via return Promise.reject(error);

here is interceptor example

axios.interceptors.response.use(
  response => {
    //maybe process here
    return response;
  },
  error => {
    //do some global magic with error and pass back to caller
    return Promise.reject(error);
  }
);

Let's start with try/catch example that won't work

for(let i=0; i<5;i++) {

    try{
       const result = async axios.get(`${/item/{i}}`);
    }
    catch(error) {
       //error undefined here, you would expect an error from pattern like axios.get(...).then(...).catch(real_http_error) 
    }
}

I found this pattern to work. Let say you want to make calls in a loop to make avoid multiple http call due to async nature of JS.

for(let i=0; i<5;i++) {

    const result = async axios.get(`${/item/{i}}`).catch(error) {  //chain catch despite async keyword
       //now you access http error and you can do something with it
       //but calling break; or return; won't break for loop because you are in a callback
    }

    if(!result) { //due to http error
        continute; //keep looping for next call
        //or break; to stop processing after 1st error
    }
    
    //process response here, result.data...
}

Upvotes: 8

Lev K.
Lev K.

Reputation: 402

In my solution I use:

try{
    let responseData = await axios.get(this.apiBookGetBookPages + bookId, headers);
    console.log(responseData);
}catch(error){
    console.log(Object.keys(error), error.message);
}

If something failed we will get en error like this:

[ 'config', 'request', 'response', 'isAxiosError', 'toJSON' ] 
'Request failed with status code 401'

We can also get status code:

...
}catch(error){
    if(error.response && error.response.status == 401){
            console.log('Token not valid!');
    }
}

Upvotes: 9

Maxime
Maxime

Reputation: 415

You can keep almost the same function

const getToken = async () => {
  try {
    const token = await axios.post(keys.sessionURL, {
      email: keys.verificationEmail,
      password: keys.verificationPassword,
    })
  } catch (err) {
    throw new Error('Unable to get a token.')
  }
}

Then from your route handler just catch the eventual exception

app.get('/endpoint', async (req, res) => {
  try {
    const token = await getToken()

    // Do your stuff with the token
    // ...

  } catch (err) {
     // Error handling here
     return res.status(401).send(err.message);
  }
})

The default js exception system works well to pass error data through the call stack.

Upvotes: 20

Atishay Jain
Atishay Jain

Reputation: 1445

you keep a flag like isAuthError and if error occurs send it as true and in the main function if the flag isAuthError is true throw the err and handle in catch otherwise perform your operations. I've added an example below. hope it helps

const getToken = async () => {
    try {
      const token = await axios.post(keys.sessionURL, {
        email: keys.verificationEmail,
        password: keys.verificationPassword,
      });
      return {token, isAuthError: false};
    } catch (err) {
      // throw new Error('Unable to establish a login session.'); // here I'd like to send the error to the user instead
      return {err, isAuthError: true};
    }
  };

mainFunction

app.post('/login', async (req, res)=>{
  try{
    // some validations

    let data = await getToken();
    if( data.isAuthError){
      throw data.err;
    }
    let token = data.token;
    //do further required operations
  }catch(err){
     //handle your error here with whatever status you need
     return res.status(500).send(err);
  }
})

Upvotes: 6

Related Questions