Skip to content

Instantly share code, notes, and snippets.

@khovansky-al
Created February 2, 2018 20:47
Show Gist options
  • Save khovansky-al/54e69a7c92211c24e3c9750e03ddca28 to your computer and use it in GitHub Desktop.
Save khovansky-al/54e69a7c92211c24e3c9750e03ddca28 to your computer and use it in GitHub Desktop.
/*
Ported from https://github.com/zslucky/redux-fetch-middleware
and fixed (though some things are still broken) by @khovansky
*/
import { merge } from 'lodash'
import uuid from 'uuid'
import defaultConfig from './config'
// Default response type for module
const defaultRType = 'json'
function checkResponseType(type) {
const validType = String(type).toLowerCase()
const types = {
json: true,
text: true,
formData: true,
blob: true,
arrayBuffer: true,
}
return types[validType] ? validType : defaultRType
}
function restMiddlewareCreator(customConfig) {
const finalConfig = merge(defaultConfig, customConfig)
const { suffix, fetchOptions, responseType: configRType, debug } = finalConfig
return ({ dispatch, getState }) => next => (action) => {
if (!action || !action.$payload) {
return next(action)
}
const [REQUEST, SUCCESS, FAILURE] = suffix
const { type, $payload, meta } = action
const { url, options, onResponse, preFetchOptions, interceptors } = $payload
let opts = merge({}, fetchOptions, options)
// Edit fetch options in preFetchOptions method
if (preFetchOptions instanceof Function) {
opts = preFetchOptions(getState, opts)
}
// Check and get response type
const finalRType = checkResponseType($payload.responseType || configRType)
// Generate UID request if meta.$uid is empty
const uid = meta && meta.$uid ? meta.$uid : uuid.v4()
const preMeta = merge(
{},
{ $uid: uid },
(debug ? { $requestOptions: opts } : {}),
meta,
)
let resultMeta = null
// Request start
dispatch({ type: `${type}_${REQUEST}`, meta: preMeta })
// Catch the response from service
return fetch(url, opts)
.then((response) => {
resultMeta = merge({}, { $response: response }, preMeta)
const responseJSON = response[finalRType]()
if (
onResponse
&& (onResponse instanceof Function)
&& onResponse(response, preMeta, type) === false
) {
throw responseJSON
}
return responseJSON
})
.then((data) => {
// Request success, dispatch the response data
dispatch({ type: `${type}_${SUCCESS}`, data, meta: resultMeta })
if (
interceptors &&
interceptors.success &&
interceptors.success instanceof Function
) interceptors.success({ dispatch, getState, data })
})
.catch((err) => {
// Request failure, dispatch the error
dispatch({ type: `${type}_${FAILURE}`, err, meta: resultMeta })
if (
interceptors &&
interceptors.failure &&
interceptors.failure instanceof Function
) interceptors.failure({ dispatch, getState, err })
})
}
}
export default restMiddlewareCreator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment