问题
I am using redux-observable and this is what I am trying to do.
When an actiontype of 'APPLY_SHOPPING_LIST' comes in dispatch 'APPLYING_SHOPPING_LIST' and after 5 seconds dispatch 'APPLIED_SHOPPING_LIST'. This is the code that I have come up with so far
const applyingShoppingListSource = action$.ofType('APPLY_SHOPPING_LISTS').mapTo({ type: 'APPLYING_SHOPPING_LISTS' }); const applyingShoppingListSourceOther = action$.ofType('APPLY_SHOPPING_LISTS').mapTo({ type: 'APPLIED_SHOPPING_LISTS' }).delay(5000); const concatList = applyingShoppingListSource.concat(applyingShoppingListSourceOther);
return concatList;
Now the problem is that only 'APPLYING_SHOPPING_LISTS' gets fired, the 'APPLIED_SHOPPING_LISTS' does not get fired to the reducer at all. Am I missing something here?
Just to add to this, when I used flatMap it worked, given below is the code
return action$.ofType('APPLY_SHOPPING_LISTS')
.flatMap(() => Observable.concat(Observable.of({ type: 'APPLYING_SHOPPING_LISTS' }), Observable.of({ type: 'APPLYING_SHOPPING_LISTS' });
I am confused how this works and the other does not?
回答1:
There's a couple issues. Since Observables are lazy, your second action$.ofType('APPLY_SHOPPING_LISTS')
for applyingShoppingListSourceOther
is being concat'd after the first applyingShoppingListSource
, so it won't be listening for APPLY_SHOPPING_LISTS
until after the first one is has completed, but it will never realistically complete because you're taking all actions that match, forever.
Said another way, your code does this:
- Start listening for
APPLY_SHOPPING_LISTS
and when received map it toAPPLYING_SHOPPING_LISTS
- When that first Observable completes (it never does) start listening for
APPLY_SHOPPING_LISTS
again, this time when received map it toAPPLIED_SHOPPING_LISTS
but wait 5000 ms before emitting it.
You could solve the particular issue of the first not ever completing by using .take(1)
or .first()
(same thing), but you usually need to write your epics to not ever stop listening so they respond to actions at any time.
I think what you want is this:
const exampleEpic = action$ =>
action$.ofType('APPLY_SHOPPING_LISTS')
.mergeMap(() =>
Observable.of({ type: 'APPLYING_SHOPPING_LISTS' })
.concat(
Observable.of({ type: 'APPLIED_SHOPPING_LISTS' })
.delay(5000)
)
);
I used mergeMap
but you may want to use switchMap
to cancel any previously pending APPLIED_SHOPPING_LISTS
that haven't emitted yet. Your call.
来源:https://stackoverflow.com/questions/43748453/redux-observable-return-multiple-action-types