Skip to content

Commit 174ceda

Browse files
committed
feat(ofType): add operator to provided actions observable
This adds an `ofType` operator to the actions observable provided to the dispatched function that will be available anywhere in the operator chain for that observable. It basically filters by the action's type, which is a common need.
1 parent ab33766 commit 174ceda

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

src/actions-observable.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Observable } from 'rxjs/Observable';
2+
import { filter } from 'rxjs/operator/filter';
3+
4+
export class ActionsObservable extends Observable {
5+
constructor(actionsSubject) {
6+
super();
7+
this.source = actionsSubject;
8+
}
9+
10+
lift(operator) {
11+
const observable = new ActionsObservable(this);
12+
observable.operator = operator;
13+
return observable;
14+
}
15+
16+
ofType(key) {
17+
return this::filter((action) => action.type === key);
18+
}
19+
}

src/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { Subject } from 'rxjs/Subject';
22
import { from } from 'rxjs/observable/from';
3+
import { ActionsObservable as Actions } from './actions-observable';
34

45
export function reduxObservable() {
56
let actions = new Subject();
7+
let actionsObs = new Actions(actions);
68

79
let middleware = (store) => (next) => {
810
return (action) => {
911
if (typeof action === 'function') {
10-
let obs = from(action(actions, store));
12+
let obs = from(action(actionsObs, store));
1113
let sub = obs.subscribe(next);
1214
return sub;
1315
} else {
@@ -19,3 +21,5 @@ export function reduxObservable() {
1921

2022
return middleware;
2123
}
24+
25+
export const ActionsObservable = Actions;

test/actions-observable-spec.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* globals describe it */
2+
import { expect } from 'chai';
3+
import { ActionsObservable, reduxObservable } from '../';
4+
import { createStore, applyMiddleware } from 'redux';
5+
import { of } from 'rxjs/observable/of';
6+
import { Subject } from 'rxjs/Subject';
7+
8+
describe('ActionsObservable', () => {
9+
it('should exist', () => {
10+
expect(ActionsObservable).to.be.a('function');
11+
});
12+
13+
it('should be the type provided to a dispatched function', () => {
14+
let middleware = reduxObservable();
15+
let reducer = (state, action) => {
16+
return state;
17+
};
18+
19+
let store = createStore(reducer, applyMiddleware(middleware));
20+
21+
store.dispatch((arg1) => {
22+
expect(arg1).to.be.an.instanceof(ActionsObservable);
23+
return of({ type: 'WEEE' });
24+
});
25+
});
26+
27+
it('should have a ofType operator that filters by action type', () => {
28+
let actions = new Subject();
29+
let actionsObs = new ActionsObservable(actions);
30+
let lulz = [];
31+
let haha = [];
32+
33+
actionsObs.ofType('LULZ').subscribe(x => lulz.push(x));
34+
actionsObs.ofType('HAHA').subscribe(x => haha.push(x));
35+
36+
actions.next({ type: 'LULZ', i: 0 });
37+
38+
expect(lulz).to.deep.equal([{ type: 'LULZ', i: 0 }]);
39+
expect(haha).to.deep.equal([]);
40+
41+
actions.next({ type: 'LULZ', i: 1 });
42+
43+
expect(lulz).to.deep.equal([{ type: 'LULZ', i: 0 }, { type: 'LULZ', i: 1 }]);
44+
expect(haha).to.deep.equal([]);
45+
46+
actions.next({ type: 'HAHA', i: 0 });
47+
48+
expect(lulz).to.deep.equal([{ type: 'LULZ', i: 0 }, { type: 'LULZ', i: 1 }]);
49+
expect(haha).to.deep.equal([{ type: 'HAHA', i: 0 }]);
50+
});
51+
});

0 commit comments

Comments
 (0)