Skip to content

Instantly share code, notes, and snippets.

@eagsalazar
Last active March 27, 2016 20:34
Show Gist options
  • Save eagsalazar/56bc0ce04fadc81ac9da to your computer and use it in GitHub Desktop.
Save eagsalazar/56bc0ce04fadc81ac9da to your computer and use it in GitHub Desktop.
Async middleware with Redux example
export const getFeedItem = feedItemId => (
{
type: GET_FEED_ITEM,
ajax: true,
payload: {
type: 'get',
route: `/feed/${feedItemId}`,
pending: GET_FEED_ITEM_PENDING,
success: GET_FEED_ITEM_SUCCESS,
failure: GET_FEED_ITEM_FAILURE,
},
}
)
import superagent from 'superagent'
import Immutable from 'immutable'
const { API_BASE_URL } = __ENV__
const API_VERSION = '/api/v1'
const API_URL = API_BASE_URL + API_VERSION
let responseCache = Immutable.Map()
const stringifiedQuery = query => query ? JSON.stringify(query) : ''
const responseFromCache = (route, query) => (
responseCache.get(`${route}${stringifiedQuery(query)}`) || Immutable.Map()
)
const cacheResponse = (response, route, query) => (
responseCache = responseCache.set(
`${route}${stringifiedQuery(query)}`,
Immutable.fromJS(response.body)
)
)
export default () => next => action => {
const { ajax, cache } = action
if (!ajax) return next(action)
const ajaxTypes = {
get: superagent.get,
post: superagent.post,
put: superagent.put,
}
const { pending, success, failure, route, query, body } = action.payload
next({
type: pending,
payload: cache ? responseFromCache(route, query) : Immutable.fromJS(body || {}),
})
return ajaxTypes[action.payload.type.toLowerCase()](API_URL + route)
.set('authorization', `Bearer ${window.sessionStorage.getItem('token')}`)
.query(query)
.send(body)
.end((err, response) => {
if (err) {
next({
type: failure,
})
} else {
if (cache) cacheResponse(response, route, query)
next({
type: success,
payload: Immutable.fromJS(response.body),
})
}
})
}
@eagsalazar
Copy link
Author

Q: Hey would you say using redux-thunk represents your latest and greatest take on async behavior that changes state on the server and the client?
A: redux-thunk is good, but these days I prefer to make a custom redux middleware to handle ajax stuff

---- middleware.js

^^ Here’s the one I’m currently using for the now redux-ified XXXXXXX app
There’s some stuff to deal with caching and a few circumstancs specific to the project, but I think you can get the idea from it, and see how simple it can be.

basically to use this you would include an ajax: true attribute on your action, plus attributes for the names of the pending, success, and failure actions. So a typical action creator would look like:

----action_creator.js

the middleware intercepts that action, and then sends along the relevant pendind, success, or failure action instead.

One of the things I like about this approach is you keep all of the async stuff in one place, so you get to write something resembling syncronous code everywhere else

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment