Skip to content

Commit

Permalink
Merge pull request #53 from piranna/discard
Browse files Browse the repository at this point in the history
Allow to use Promises on `discard` function
  • Loading branch information
sorodrigo authored Oct 24, 2017
2 parents ef08431 + 771f093 commit 0c2e1ce
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ export type Config = {
detectNetwork: (callback: NetworkCallback) => void,
effect: (effect: any, action: OfflineAction) => Promise<*>,
retry: (action: OfflineAction, retries: number) => ?number,
discard: (error: any, action: OfflineAction, retries: number) => boolean,
discard: (error: any, action: OfflineAction, retries: number) => boolean|Promise<boolean>,
defaultCommit: { type: string },
defaultRollback: { type: string },
persist: (store: any) => any,
Expand Down Expand Up @@ -446,7 +446,7 @@ const config = {
}
```
The method receives the Error returned by the effect reconciler, the action being processed, and a number representing how many times the action has been retried. If the method returns `true`, the action will be discarded; `false`, and it will be retried. The full signature of the method is `(error: any, action: OfflineAction, retries: number) => boolean`.
The method receives the Error returned by the effect reconciler, the action being processed, and a number representing how many times the action has been retried. If the method returns `true`, the action will be discarded; `false`, and it will be retried. The full signature of the method is `(error: any, action: OfflineAction, retries: number) => boolean`. Alternatively, you can return a Promise object that resolve to a boolean, allowing you to detect when to discard asynchronously (for example, doing a request to a server to refresh a token and try again).
#### Change how network requests are retried
Expand Down
28 changes: 28 additions & 0 deletions src/__tests__/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,34 @@ describe('when request fails', () => {
expect(dispatch).toBeCalledWith(expect.objectContaining(completedMeta));
});
});

test('dispatches complete action with promised discard', () => {
const effect = () => Promise.reject();
const discard = () => Promise.resolve(true);
const { action, config, dispatch } = setup({ effect, discard });
const promise = send(action, dispatch, config);

const { rollback } = action.meta.offline;
expect.assertions(2);
return promise.then(() => {
expect(dispatch).toBeCalledWith(expect.objectContaining(rollback));
expect(dispatch).toBeCalledWith(expect.objectContaining(completedMeta));
});
});

test('dispatches complete action when discard throw an exception', () => {
const effect = () => Promise.reject();
const discard = () => {throw new Error};
const { action, config, dispatch } = setup({ effect, discard });
const promise = send(action, dispatch, config);

const { rollback } = action.meta.offline;
expect.assertions(2);
return promise.then(() => {
expect(dispatch).toBeCalledWith(expect.objectContaining(rollback));
expect(dispatch).toBeCalledWith(expect.objectContaining(completedMeta));
});
});
});

describe('when request succeeds and commit is undefined', () => {
Expand Down
22 changes: 14 additions & 8 deletions src/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,28 @@ const send = (action: OfflineAction, dispatch, config: Config, retries = 0) => {
dispatch(complete({ type: JS_ERROR, payload: e }, false));
}
})
.catch(error => {
.catch(async error => {
const rollbackAction = metadata.rollback || {
...config.defaultRollback,
meta: { ...config.defaultRollback.meta, offlineAction: action }
};

// discard
if (config.discard(error, action, retries)) {
dispatch(complete(rollbackAction, false, error));
return;
let mustDiscard = true;
try {
mustDiscard = await config.discard(error, action, retries);
} catch (e) {
console.warn(e);
}
const delay = config.retry(action, retries);
if (delay != null) {
dispatch(scheduleRetry(delay));
return;

if (!mustDiscard) {
const delay = config.retry(action, retries);
if (delay != null) {
dispatch(scheduleRetry(delay));
return;
}
}

dispatch(complete(rollbackAction, false, error));
});
};
Expand Down

0 comments on commit 0c2e1ce

Please sign in to comment.