Skip to content

Commit

Permalink
feat(Adapters): Adds support for Epic input/output adapters.\nThis al…
Browse files Browse the repository at this point in the history
  • Loading branch information
jayphelps authored and benlesh committed Aug 1, 2016
1 parent ea4311e commit a662cdf
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 12 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
## Install

This has a peer dependencies of `rxjs@5.0.*` and `redux`, which will have to be installed
as well. **It is not currently compatible with RxJS v4**
as well. Support for RxJS v4 can temporarily be provided by [an optional adapter](https://github.com/redux-observable/redux-observable-adapter-rxjs-v4).

```sh
npm install --save redux-observable
Expand Down
10 changes: 4 additions & 6 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,17 @@
## General

<a id="general-rxjs-v4"></a>
### Does this work with RxJS 4/most.js/bacon.js?
### Does this work with RxJS 4/most.js/bacon.js/etc?

##### RxJS v4

Not out of box. We'd love to provide an elegant solution for this soon; ideally [RxJS v4 would add interop with `Symbol.observable`](https://github.com/Reactive-Extensions/RxJS/issues/1225).
Not out of box, but we provide an adapter [redux-observable-adapter-rxjs-v4](https://github.com/redux-observable/redux-observable-adapter-rxjs-v4) you can install to add support temporarily while you transition to RxJS v5. Please upgrade to v5 as soon as possible as we do not plan to support this long-term.

##### most.js

We believe so, but this is currently unconfirmed! (please let us know) [most.js supports interop](https://github.com/cujojs/most/blob/master/docs/api.md#draft-es-observable-interop) with the proposed ECMAScript Observable spec which RxJS builds on top of.

##### bacon.js
##### etc.

Not out of box. Some work has been done to make [bacon.js support](https://github.com/baconjs/bacon.js/issues/633) the `Symbol.observable` interop point.
It should be possible for you to create an adapter to add support. See [redux-observable-adapter-rxjs-v4](https://github.com/redux-observable/redux-observable-adapter-rxjs-v4) for reference.

<a id="miscellaneous-thunkservables-deprecated"></a>
### Why were thunkservables deprecated?
Expand Down
21 changes: 16 additions & 5 deletions src/createEpicMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,20 @@ import { switchMap } from 'rxjs/operator/switchMap';
import { ActionsObservable } from './ActionsObservable';
import { EPIC_END } from './EPIC_END';

export function createEpicMiddleware(epic) {
const actionsSubject = new Subject();
const action$ = new ActionsObservable(actionsSubject);
const defaultAdapter = {
input: action$ => action$,
output: action$ => action$
};

const defaultOptions = {
adapter: defaultAdapter
};

export function createEpicMiddleware(epic, { adapter = defaultAdapter } = defaultOptions) {
const input$ = new Subject();
const action$ = adapter.input(
new ActionsObservable(input$)
);
const epic$ = new BehaviorSubject(epic);
let store;

Expand All @@ -16,7 +27,7 @@ export function createEpicMiddleware(epic) {

return next => {
if (typeof epic === 'function') {
epic$::switchMap(epic => epic(action$, store))
epic$::switchMap(epic => adapter.output(epic(action$, store)))
.subscribe(store.dispatch);
}

Expand All @@ -30,7 +41,7 @@ export function createEpicMiddleware(epic) {
return out$.subscribe(store.dispatch);
} else {
const result = next(action);
actionsSubject.next(action);
input$.next(action);
return result;
}
};
Expand Down
20 changes: 20 additions & 0 deletions test/createEpicMiddleware-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,24 @@ describe('createEpicMiddleware', () => {
done();
}, 100);
});

it('supports an adapter for Epic input/output', () => {
const reducer = (state = [], action) => state.concat(action);
const epic = input => input + 1;

const adapter = {
input: () => 1,
output: value => of({
type: value + 1
})
};
const middleware = createEpicMiddleware(epic, { adapter });

const store = createStore(reducer, applyMiddleware(middleware));

expect(store.getState()).to.deep.equal([
{ type: '@@redux/INIT' },
{ type: 3 }
]);
});
});

0 comments on commit a662cdf

Please sign in to comment.