Reputation: 107
Using redux-observable, I'm trying to spawn off multiple WORK
actions from a single epic, like so:
( action$, state$ ) => {
return action$.pipe(
ofType( 'SPAWN' ),
flatMap( action => {
return [
{ type: 'WORK', payload: 'a' },
{ type: 'WORK', payload: 'b' },
{ type: 'WORK', payload: 'c' },
];
} )
)
}
The actions are firing off fine, but problem is, these WORK
actions are async and thus they are handled by another epic, like so:
( action$, state$ ) => {
return action$.pipe(
ofType( 'WORK' ),
flatMap( action => {
const promise = new Promise( resolve => {
setTimeout( () => {
resolve( { type: 'SET', payload: action.payload } );
}, Math.random() * 5000 ); // promise may resolve at different times
} );
return promise;
} )
)
}
At the reducer for action SET
, I would expect, the sequence to be in order, regardless of the randomness of the setTimeout
above, since the flatMap is returning promises. The result should be like so:
a
b
c
Nonetheless, I'm getting random orderings for the SET
action, for example:
b
c
a
Would really appreciate it if anyone can point me to the right direction and aid me in my understanding.
Working Update
As per the answer from @Oles Savluk, I've edited the WORK
epic to be as follows:
( action$, state$ ) => {
return action$.pipe(
ofType( 'WORK' ),
concatMap( action => {
const promise = new Promise( resolve => {
setTimeout( () => {
resolve( { type: 'SET', payload: action.payload } );
}, Math.random() * 5000 ); // promise may resolve at different times
} );
return promise;
} )
)
}
Notice that the use of concatMap
makes actions of the type WORK
to be arranged in the stream sequentially. One action waits for another to complete before executing.
Upvotes: 2
Views: 3087
Reputation: 4345
You need to use concatMap
operator which will emit items sequentially instead of flatMap
(mergeMap) which do this concurrently
If you are new to Rx you can read this article to understand the difference between flattening operators.
Upvotes: 2
Reputation: 14199
With flatMap
, all emissions of the inner observable are forwarded to the outer observable in order of their occurance. Now, with a Promise
, that emission is created only when the Promise resolves, not immediately. Therefore, you receive the "random" order that is created by the timeout.
Upvotes: 1