Reputation: 2675
I have a dataService function in React that does my API fetching. I tried converting to async/await block but seem to hit a roadblock.
Using promises:
const dataService = (url, options, dataToPost) => {
return (dispatch, getState) => {
const { requestAction, successAction, failureAction } = options.actions;
if (options.shouldRequest(getState())) {
dispatch(requestAction());
const promise = axios.get(url, { withCredentials: true });
return promise
.then(response => {
if (response.status === 200) {
return dispatch(successAction(response, dispatch));
}
return Promise.reject(response);
})
.catch(error => {
if (error.response.status === 302) {
window.location = '/view';
}
dispatch(openErrorDialog());
return dispatch(failureAction(error));
});
}
return Promise.reject(new Error('FETCHING'));
};
};
Using async/await:
const dataService = async (url, options, dataToPost) => {
return async (dispatch, getState) => {
let url;
const {requestAction, successAction, failureAction} = options.actions;
if (options.shouldRequest(getState())) {
dispatch(requestAction());
const promise = axios.get(url, {withCredentials: true});
try {
const response = await promise;
if (response.status === 200) {
return dispatch(successAction(response, dispatch));
}
return Promise.reject(response);
} catch (error) {
return dispatch(failureAction(error));
}
}
return Promise.reject(new Error('FETCHING'));
};
};
The error is "Actions must be plain objects. Use custom middleware for async actions.". The promises code works perfecty. I am already using thunk. Please advice.
Upvotes: 8
Views: 30729
Reputation: 1
If you truly want to change Promise -> async/await then the changes are as follows:
For a start, you DONT want dataService to be async
as that will mean it returns a Promise, which changes how it needs to be called - you dont' wnat that
Secondly, changing
const promise = axios.get ...
promise.then(response ....
to
const promise = await axios.get ...
promise.then(response ....
wont work ...
it needs to be
const response = await axios.get ...
no need for the promise variable
Even so, you're still using promises in your converted code ... which now is only different by having async
keywords for no reason
Here's how your (original) code should be converted to async/await
note the total LACK of the word Promise in what follows:
const dataService = (url, options, dataToPost) => {
return async (dispatch, getState) => {
const { requestAction, successAction, failureAction } = options.actions;
if (options.shouldRequest(getState())) {
const data = typeof dataToPost === 'string' ? { data: dataToPost } : dataToPost;
dispatch(requestAction());
try {
const response = dataToPost
? await axios.post(url, data, { withCredentials: true })
: await axios.get(url, { withCredentials: true });
if (response.status === 200) {
return dispatch(successAction(response, dispatch));
}
throw response;
} catch(error) {
if (error.response.status === 302) {
window.location = '/view';
}
dispatch(openErrorDialog());
return dispatch(failureAction(error));
}
}
throw new Error('FETCHING');
};
};
Upvotes: 14
Reputation: 632
await axios.post(url, data, { withCredentials: true })
does not return promise, it returns the real response of the request.
do not use then-catch when using async-await, use try-catch instead. here is the fix
try {
const response = dataToPost
? await axios.post(url, data, { withCredentials: true })
: await axios.get(url, { withCredentials: true });
if (response.status === 200) {
return dispatch(successAction(response, dispatch));
}
return Promise.reject(response);
} catch (err) {
if (error.response.status === 302) {
window.location = '/view';
}
dispatch(openErrorDialog());
return dispatch(failureAction(error));
}
Upvotes: 5