Skip to content

Instantly share code, notes, and snippets.

@borisd
Created June 26, 2016 16:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borisd/eec23009ef321121dece49508a1b3881 to your computer and use it in GitHub Desktop.
Save borisd/eec23009ef321121dece49508a1b3881 to your computer and use it in GitHub Desktop.
API middleware
const API = 'API';
const API_STARTED = 'API_STARTED';
const API_ERROR = 'API_ERROR';
const API_DONE = 'API_DONE';
const CANCEL_API = 'CANCEL_API';
const API_ROOT = 'https://s3.amazonaws.com/500tech-shared/';
const apiAction = {
type: API,
request: {
url: 'users.json',
method: 'GET'
},
response: {
success: 'SET_USERS',
error: 'NONE',
pending: 'NONE'
},
meta: {
skipAuth: false
}
};
const canceled = {};
const apiMiddleware = ({ dispatch, getState }) => next => action => {
function setupRequest({ url, method = 'GET', body }) {
const { accessToken } = getState().currentUser || {};
const { skipAuth } = action.meta || {};
const { pending } = action.response;
const params = { method };
// Notify system that an API request has started
dispatch({ type: pending ? pending : API_STARTED });
if (!skipAuth && accessToken) {
params.headers = { accessToken }
}
if (method === 'POST') {
params.body = JSON.stringify(body);
}
return fetch(API_ROOT + url, params);
}
const checkStatus = response => {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
var error = new Error(response.statusText);
error.response = response;
throw error;
}
};
const handleResponse = data => {
const { success } = action.response;
const { cancelable } = action.meta || {};
if (cancelable && canceled[cancelable]) {
return;
}
dispatch({ type: success, payload: data });
dispatch({ type: API_DONE });
};
const handleError = error => {
const errorAction = action.response.error;
const { cancelable } = action.meta || {};
if (cancelable && canceled[cancelable]) {
return;
}
if (errorAction) {
dispatch({type: errorAction, error});
}
dispatch({ type: API_ERROR, error });
};
switch (action.type) {
case API:
setupRequest(action.request)
.then(checkStatus)
.then(response => response.json())
.then(handleResponse)
.catch(handleError);
break;
case CANCEL_API:
canceled[action.id] = true;
setTimeout(() => delete canceled[action.id], 5000);
break;
}
return next(action);
};
export default apiMiddleware;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment