9

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.

2
  • what you've done makes no sense, in that const promise = dataToPost ? .... wont be a promise - lets face it, all you've done is mark dataService as async, so now it doesn't return the function declared within, it returns a promise of that function Commented Mar 21, 2019 at 2:06
  • Try removing async keyword from dataService to dataService = (url, options, dataToPost) This might help: stackoverflow.com/questions/50059724/… Commented Mar 21, 2019 at 2:08

2 Answers 2

14

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');
    };
};
Sign up to request clarification or add additional context in comments.

Comments

5

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));
}

1 Comment

@Ben: ??? Every async function returns a Promise object. The await statement operates on a Promise, waiting until the Promise resolves` or rejects. So @Gianfranco Fertino is correct.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.