'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!
Solution 1:[1]
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.
Solution 2:[2]
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!');
}
}
Solution 3:[3]
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);
}
})
Solution 4:[4]
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...
}
Solution 5:[5]
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
Solution 6:[6]
Elegant & with TypeScript.
import axios, { AxiosResponse } 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: unknown) => {
if (error instanceof Error) {
console.error(
"Error with fetching ..., details: ",
error
);
}
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | its4zahoor |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | |
| Solution 5 | Dreamoon |
| Solution 6 | Daniel Danielecki |
