Add transaction capability to asyncActions

for relating pending/success/failure actions. Particularly useful for mapping
a failure to a pending action to roll back any optimistic updates.
pull/21833/head
lukebarnard 2018-01-25 21:45:15 +01:00
parent 02824cfacf
commit 38de8a129b
1 changed files with 14 additions and 2 deletions

View File

@ -31,18 +31,30 @@ limitations under the License.
* `${id}.pending` and either * `${id}.pending` and either
* `${id}.success` or * `${id}.success` or
* `${id}.failure`. * `${id}.failure`.
*
* The shape of each are:
* { action: '${id}.pending', request, asyncId }
* { action: '${id}.success', result, asyncId }
* { action: '${id}.failure', err, asyncId }
*
* where `request` is returned by `pendingFn`, result
* is the result of the promise returned by `fn` and
* `asyncId` is a unique ID for each dispatch of the
* asynchronous action.
*/ */
export function asyncAction(id, fn, pendingFn) { export function asyncAction(id, fn, pendingFn) {
return (dispatch) => { return (dispatch) => {
const asyncId = Math.random().toString(16).slice(2, 10);
dispatch({ dispatch({
action: id + '.pending', action: id + '.pending',
request: request:
typeof pendingFn === 'function' ? pendingFn() : undefined, typeof pendingFn === 'function' ? pendingFn() : undefined,
asyncId,
}); });
fn().then((result) => { fn().then((result) => {
dispatch({action: id + '.success', result}); dispatch({action: id + '.success', result, asyncId});
}).catch((err) => { }).catch((err) => {
dispatch({action: id + '.failure', err}); dispatch({action: id + '.failure', err, asyncId});
}); });
}; };
} }