I've been playing around with using async
and await
in my Redux reducers to get rid of all the Promise callback functions - this stuff's like magic!
Note: I'm using Webpack and compiling with the babel-preset-stage-0
for ES2016 await/async.
Before
This is my login function using a Promise and fetch
to send data to the API:
export const login = (username, password) => {
// using thunk middleware since it's async, so return a function
return dispatch => {
// create data to send via fetch
const data = new FormData();
data.append('username', username);
data.append('password', password);
// fire the request
fetch('http://localhost/login', {
method: 'POST',
body: data
})
// wait for data back
.then(response => response.json())
// response.json() is also async, so wait for that to finish
.then(data => dispatch(loginSuccess(data)))
// catch any errors
.catch(err => dispatch(loginFailure(err)));
};
};
After
Here's the function now I'm using async
/await
: I've split it into two functions so the async login request isn't nested. There's also no callback then()
functions!
// this just wraps fetch - a simpler 'GET' could just be inline
// note the 'async' keyword
async function loginRequest (username, password) {
const data = new FormData();
data.append('username', username);
data.append('password', password);
// 'await' the response from fetch - no callback, you can just carry on
// and use 'response' as normal rather than wrap it in a function!
const response = await fetch('http://localhost/login', {
method: 'POST',
body: data
});
// response.json() is async too, but you don't need an 'await'
// keyword in a return from 'async' (it's implied)
return response.json();
}
// this is the reducer - no 'async' on the outer function since it just returns a function
export const login = (username, password) => {
// this one's 'async'
return async dispatch => {
// wrap in try to listen for Promise rejections - equivalent of '.catch()'
try {
// wait for the fetch to finish then dispatch the result
const data = await loginRequest(username, password);
dispatch(loginSuccess(data));
} catch (e) {
// catch errors from fetch
dispatch(loginFailure(e));
}
};
};