Reputation: 1996
I'm trying to create an epic that will take an action, and then dispatch two different actions, with the second one delayed by two seconds. After a bunch of attempts, this was the best I could do:
const succeedEpic = action$ =>
action$.filter(action => action.type === 'FETCH_WILL_SUCCEED')
.mapTo({ type: 'FETCH_REQUEST' })
.merge(Observable.of({ type: 'FETCH_SUCCESS' }).delay(2000))
Unfortunately, it seems that:
Observable.of({ type: 'FETCH_SUCCESS' }).delay(2000)
Is run immediately upon my app being loaded (rather than when an event comes down the parent stream). I noticed this because the FETCH_SUCCESS
action is received by the reducer exactly two seconds after my app is loaded. I even attached a console.log
to confirm this:
const succeedEpic = action$ =>
action$.filter(action => action.type === 'FETCH_WILL_SUCCEED')
.mapTo({ type: 'FETCH_REQUEST' })
.merge(Observable.of({ type: 'FETCH_SUCCESS' })
.do(() => console.log('this has begun'))
.delay(2000)
)
"this has begun" is logged to the console the moment the app is started.
I suspect this has something to do with how Redux-Observable automatically subscribes for you.
The desired behaviour is that I will:
FETCH_WILL_SUCCEED
event.FETCH_REQUEST
event is dispatched.FETCH_SUCCESS
event is dispatched.Upvotes: 0
Views: 2350
Reputation: 1996
It turns out I needed to wrap both of my events inside a mergeMap
. Thanks to @dorus on the RxJS Gitter channel for this answer.
This is my working result:
const succeedEpic = action$ =>
action$.filter(action => action.type === 'FETCH_WILL_SUCCEED')
.mergeMapTo(Observable.of({ type: 'FETCH_REQUEST' })
.concat(Observable.of({ type: 'FETCH_SUCCESS' })
.delay(1000)))
merge
should work as well in place of concat
, but I thought concat
makes better semantic sense.
Upvotes: 2
Reputation: 13807
There might be a more elegant solution, but why not just use 2 epics and combine them?
The first one dispatches the fetch request:
const onFetchWillSucceed = action$ => action$.ofType('FETCH_WILL_SUCCEED')
.mapTo({ type: 'FETCH_REQUEST' })
The second one waits 2 secs and dispatches the success:
const onFetchRequest = action$ => action$.ofType('FETCH_REQUEST')
.delay(2000)
.mapTo({ type: 'FETCH_SUCCESS' })
And in the end they are just combined into 1 epic
const both = combineEpics(onFetchWillSucceed, onFetchRequest)
Upvotes: 0