-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathindex.js
75 lines (73 loc) · 3.14 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
* Reducer function to handle pending requests.
* @param {Object} state Existing state object.
* @param {Object} action Incoming action:
* - Actions with the meta.httpRequest property are examined.
* - The meta.httpRequest.url property is added or removed
* from the current state depending on if the meta.httpRequest.done
* property is set.
* @return {Object} The new state.
*/
export function requestsReducer(state = {}, action) {
if (!action.meta || !action.meta.httpRequest || !action.meta.httpRequest.url) {
return state;
}
if (action.meta.httpRequest.done) {
// Remove this request from the state
let newState = { ...state };
delete newState[action.meta.httpRequest.url];
return newState;
}
else {
// Add this request to the state
return { ...state, [action.meta.httpRequest.url]: true };
}
}
/**
* Creates a Redux middleware function when called.
* @param {Function} selectorFunc A function to select the location in the store's state tree where
* the requests reducer keeps it's state.
* @return {Function} A middleware function that will only dispatch the action if the
* action.meta.httpRequest.done property is false, and the
* meta.httpRequest.url is not already in flight.
*/
export function createRequestMiddleware(selectorFunc = state => state.requests) {
return store => next => action => {
// Cancel HTTP request if there is already one pending for this URL
if (action.meta && action.meta.httpRequest && !action.meta.httpRequest.done) {
const requests = selectorFunc(store.getState());
if (requests[action.meta.httpRequest.url]) {
// There is a request for this URL in flight already!
// (Ignore the action)
return;
}
}
return next(action);
};
}
/**
* Helper function to attempt a request and handle the response.
* @param {String} url The URL the request is for.
* @param {Object} actions Actions to dispatch depending on the outcome of the "makeRequest" Promise.
* @param {Function} makeRequest Function that returns a Promise object. This function performs the actual request.
* @param {Function} dispatch Redux store dispatch function.
*/
export function attemptRequest(url, actions, makeRequest, dispatch) {
const beginAction = { ...actions.begin() };
beginAction.meta = beginAction.meta || {};
beginAction.meta.httpRequest = { url, done: false };
if (!dispatch(beginAction)) {
return; // bail out here if the middleware cancelled the dispatch
}
makeRequest().then(response => {
const successAction = { ...actions.success(response) };
successAction.meta = successAction.meta || {};
successAction.meta.httpRequest = { url, done: true };
dispatch(successAction);
}).catch(err => {
const failureAction = { ...actions.failure(err) };
failureAction.meta = failureAction.meta || {};
failureAction.meta.httpRequest = { url, done: true };
dispatch(failureAction);
});
}