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