I am working with RXJS and trying to deal with sequential operations. There was a similar question RxJS queueing dependent tasks and I would have posted a comment, but I'm new :) Although I have it nearly working, what I lack is the ability to take an action after a parent operation. In the procedural world, I would conceptualize this as a nested loop, where there is some processing on each iteration of the outer loop.
With the code below, it prints "processed parent" after each child where I wanted it to run after its children are all done. I believe this is due to how concatMap flattens everything so it loses track, but I don't see a good way to to keep track of when a single parent finishes. One not so good way I came up with was to use doOnCompleted(), however that doesn't appear to let you return an observable to keep chaining.
import {Observer, Observable} from 'rx';
let parents = [
{ children: ['a', 'b'] },
{ children: ['c', 'd'] }
];
let asyncCleanup = (data) => {
return Observable.of(data)
.do(() => console.log('cleaned up', data));
};
let processParent = (parent) => {
let children = Observable.from(parent.children);
return children
.concatMap((child) => processChild(child))
.concatMap(() => asyncCleanup(parent));
};
let processChild = (child) => {
return Observable.from(child)
.do(() => console.log('processed', child));
};
Observable.from(parents)
.concatMap((parent) => processParent(parent))
.subscribe(
(data) => null,
(err) => console.error(err),
() => console.log('completed')
);
Current output:
processed a
cleaned up { children: [ 'a', 'b' ] }
processed b
cleaned up { children: [ 'a', 'b' ] }
processed c
cleaned up { children: [ 'c', 'd' ] }
processed d
cleaned up { children: [ 'c', 'd' ] }
completed
Desired output:
processed a
processed b
cleaned up { children: [ 'a', 'b' ] }
processed c
processed d
cleaned up { children: [ 'c', 'd' ] }
completed
Updated: Found a solution to this by using toArray() before .concatMap(() => asyncCleanup(parent)). Also tried bufferWithCount(parent.children.length) which worked too and is a little better to read in my opinion.