I use axios interceptors to get the error. in some cases that I have error I do not want to return to the catch or then callback.
How I do it in axios? because if I dont return value it go to the next, but if I return Promise.reject it go to the catch.
I want when I have error in interceptors, not continue forward to the callback.
codesandbox.io
import axios from "axios";
axios.interceptors.response.use(
(response) => response,
(error) => {
console.log({ error });
// do not return to the catch/then in foo please! <-- HOW?
return Promise.reject(error);
}
);
const foo = () => {
axios
.post("https://httpstat.us/500")
.then((r) => {
console.log({ r });
})
.catch((err) => {
console.log({ err });
});
};
foo();
you can return a resolve promises in the error function
axios.interceptors.response.use(
(response) => response,
(error) => {
console.log({ error });
return Promise.resolve();
}
);
Related
I'm learning React and I'm using axios and JWT for authentication. I have written an interceptor to refresh the token automatically:
privateAxios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
const { config, response } = error;
const originalRequest = config;
if (response?.status === 401) {
apiProvider
.refreshToken()
.then(() => {
let headers = getAuthHeaders();
privateAxios.defaults.headers = headers;
originalRequest.headers = headers;
return privateAxios(originalRequest);
})
.catch((err) => {
logout();
return Promise.reject(err);
});
}
return Promise.reject(error);
}
);
On my component I have the following:
api.post(data)
.then(() => {
showSuccessFeedbackForm();
reloadTable();
handleClose();
})
.catch((error) => {
setAlertInfos({
message: JSON.stringify(error.response.data),
severity: "error",
});
setShowAlert(true);
})
.finally(() => {
setIsLoaded(true);
});
My problem is that I want to continue with the component's normal "flow" (i.e., showSuccessFeedbackForm() and reloadTable() and handleClose()) if the token needed to be refreshed (when the code reaches return privateAxios(originalRequest)).
How can I accomplish this?
It looks like you should just have to return the apiProvider.refreshToken()... call. After return privateAxios(originalRequest); returns, then return Promise.reject(error); is executing which causes the front-end to receiving an rejection not a resolution.
Consider this intercepted error which does not throw an error to the frontend which still "resolves":
axios.interceptors.response.use(
(res) => res,
(err) => {
console.log("##### AXIOS ERROR #####");
dispatch(increment());
}
);
Simply changing it to this causes the front-end to catch an error which is what your code is essentially doing:
axios.interceptors.response.use(
(res) => res,
(err) => {
console.log("##### AXIOS ERROR #####");
return Promise.reject();
}
);
I have a route handler in express.js and inside it, I am calling an asynchronous function which should return me some value. I am using bluebird promises to handle the promises. Below is a sample code.
router.js
---------
router.post('/endpoint', (req, res) => {
return Promise.try(() => serviceFile.validate())
.then(() => {
console.log('Response: ', response);
})
.catch((error) => {
console.log('Error: ', error) // TypeError: expecting a function but got [object Promise]
})
})
serviceFile.js
--------------
async function validate() {
return Promise.try(() => axios.post('/endpoint'))
.then((response) => response.data)
.catch((error) => {
console.log('Error: ', error.response.data) // successfully printing the error data object
throw error;
})
}
When I call the validate() in the Service.js file, it fails the request (which I want) and successfully prints the error. But I don't want to handle the error here, so I re-throw it and expects to handle it in the router.js file. But in the router.js file, I am getting error as undefined and it says, TypeError: expecting a function but got [object Promise]
I am not getting any clue where I am doing wrong. Any help would be greatly appreciated.
its sort of unclear what serviceFile.validate does unless thats the second function you listed, this might be a more clear way of using promises
router.post('/endpoint', async (req, res) => {
try {
const response = await serviceFile.validate()
console.log('Response: ', response);
} catch (err) {
console.log('Error: ', error)
}
})
function validate () {
return new Promise(async (resolve, reject) => {
try {
const res = await axios.post('/endpoint')
resolve(res.data)
} catch (err) {
if (err.response && err.response.data) {
reject(err.response.data)
} else {
reject(err)
}
}
})
}
I would like to handle any api error via axios interceptors. However, returning only Promise.reject (error) without catch I have an error: "uncaught exception: Object"
interceptors.js:
axios.interceptors.response.use(function (response) {
return response.data;
}, function (error) {
if (error.response.status === 401) {
window.location.replace("/login");
}
return Promise.reject(error.response);
});
call.js
return axios.get("/users")
.then(data => {
return data.users;
})
.then(users => {
this.isTableLoading = false;
this.bodyData = users;
});
I tried:
add 1 global catch in only interceptors with:
Promise.resolve(error) return error: "TypeError: data is undefined";
new Promise(() => {}) work, but this is ugly...
is there a nice solution for this?
I'm performing an API call to Bing Web Search API and running into an error with the response.
Here's the code:
await webSearchApiClient.web.search(searchText).then(result => {
console.log('Results API', result)
return result
}).catch((err) => {
throw err;
})
The issue I'm running into is that the result does come back (the console log 'Results API' prints the expected return values), but the return statement isn't passing the value along. The rest of the code is written to be asynchronous, and when I print the values in the code calling the API function I get this:
Line 1: Results API {"_type": "SearchResponse","queryContext": {"originalQuery":...
Line 2: Returned Results undefined
I've tried setting the result to other variables with no success
I'm using redux as well, here's the code for the dispatch call and the code in the redux action (the second console log is the the redux actions):
const onSearchResults = async () => {
dispatch(getWebResults(searchText))
dispatch(getImageResults(searchText))
}
export const getWebResults = (searchText) => {
return async dispatch => {
const onStart = () => {
dispatch({ type: GET_WEB_RESULTS_STARTED });
}
const onSuccess = (response) => {
dispatch({ type: GET_WEB_RESULTS_SUCCESS, payload: response });
return response;
}
const onError = (error) => {
dispatch({ type: GET_WEB_RESULTS_FAILURE, payload: error });
return error;
}
try {
onStart();
const webResults = await BingWebSearchApi(searchText);
console.log('Returned Results', webResults)
return onSuccess(webResults)
} catch(error) {
return onError(error)
}
}
}
Instead of doing this
await webSearchApiClient.web.search(searchText).then(result => {
console.log('Results API', result)
return result
}).catch((err) => {
throw err;
})
Since the return statement is for the then function scope, you should return the promise like this
return webSearchApiClient.web.search(searchText);
And then in your redux actions do something like
(...)
try {
onStart();
BingWebSearchApi(searchText).then((webResults)=> {
console.log('Returned Results', webResults);
onSuccess(webResults);
});
} catch(error) {
return onError(error)
}
Hi I'm new so sorry if my question does not formulate properly.
I want to define a promise from axios js in a global function.
Here I want to handle / catch the 401 status globally and logout the user.
I do not want to handle it in every single query.
Here my source global function to handle a request:
export function requestData (url, payload = {}) {
return axios.post(url, payload)
.then(response => {
return response.data
})
.catch(error => {
if (error.response.status === 401) {
logout()
} else {
return error
}
})
}
And here a example function I use on a controller:
requestData('/api/persons', {options: this.options, search: search})
.then(data => {
this.data = data
})
.catch(error => {
this.error = error.toString()
})
My Problem is that the promise catch in my controller will not fire when there is an exception. How to realize this?
change return error in your requestData function to throw error
As per the Axios docs
You can intercept requests or responses before they are handled by then or catch.
You're going to want to use the Response Interceptor:
axios.interceptors.response.use(function(response) {
// Do something with response data
return response;
}, function(error) {
// Do something with response error
if (error.status === 401) {
logout()
}
return Promise.reject(error);
});
Replacing return error by throw error is the half work.
When I'm right the throw error in promise catch will not invoke the next promise .catch statement. This will work in the .then statement.
This way it should work:
export function requestData (url, payload = {}) {
return axios.post(url, payload)
.then(response => {
return response.data
})
.catch(error => {
if (error.response.status === 401) {
logout()
} else {
return error
}
})
.then(result => {
if (result instanceof Error) {
throw result
} else {
return result
}
})
}