Reputation: 2638
I'm using redux observable as a middleware for redux to deal with side effects. I want to dispatch action A
only when action B
was emitted more than twice in some specified period of time (say 500ms).
My attempt for this: demo
Here is how epic looks:
const pingEpic = action$ =>
action$
.buffer(action$.ofType(CLICK).throttleTime(500))
.map(x => x.length)
.filter(x => x >= 2)
.mapTo({ type: PING });
This epic correctly accumulates clicks in lists and filters those that are longer than 2, but the PING action is dispatched after another additional click.
Upvotes: 1
Views: 571
Reputation: 23473
I find it easier to nut out complicated rxjs by breaking it down into smaller bits.
So, you want to PING on a double-click and PONG on a single-click, and CLICK is the only source of events.
double-click Ref
const doubleClick = action$ =>
action$.ofType(CLICK)
.buffer(action$.ofType(CLICK).debounceTime(500))
.map(x => x.length)
.filter(x => x === 2)
.mapTo({ type: PING });
single-click
const singleClick = action$ =>
action$.ofType(CLICK)
.buffer(action$.ofType(CLICK).debounceTime(500))
.map(x => x.length)
.filter(x => x === 1)
.mapTo({ type: PONG });
PING/PONG
const pingEpic = action$ =>
Rx.Observable.merge(
singleClick(action$),
doubleClick(action$)
)
Note, it seems to work with straight replace of throttleTime
with debounceTime
,
const pingEpic = action$ =>
action$
.buffer(action$.ofType(CLICK).debounceTime(500))
.map(x => x.length)
.filter(x => x >= 2)
.mapTo({ type: PING });
but you don't get any PONGs happening with this. (Adding a console.log to the reducer shows the flow a bit better)
const pingReducer = (state = { isPinging: 'NO' }, action) => {
console.log('reducer', action.type)
...
Here's the example Fiddle
Upvotes: 1