mookie the swede mookie the swede - 3 months ago 22
Javascript Question

How to create an array from rxjs without completion of the adding sequence

I'm trying to figure out an rxjs way of doing the following:

You have two observables, one onAddObs and onRemoveObs.
let's say onAddObs.next() fires a few times, adding "A", "B", "C".
I would like to then get ["A", "B", "C"].

.toArray requires the observable be completed...yet more could come.

That's the first part. The second part is probably obvious...
I want onRemoveObs to then remove from the final resulting array.

I don't have a plunkr cuz I can't get anything close to doing this...
Thanks in advance!

UPDATE

Based on user3743222's advice, I checked out .scan, which did the job!
If anyone else has trouble with this, I've included an angular2 service which shows a nice way of doing this. The trick is to use .scan and instead of streams of what was added/removed, have streams of functions to add/remove, so you can call them from scan and pass the state.

@Injectable()
export class MyService {

public items: Observable<any>;
private operationStream: Subject<any>;

constructor() {

this.operationStream = Subject.create();

this.items = this.operationStream
// This may look strange, but if you don't start with a function, scan will not run....so we seed it with an operation that does nothing.
.startWith(items => items)
// For every operation that comes down the line, invoke it and pass it the state, and get the new state.
.scan((state, operation:Function) => operation(state), [])
.publishReplay(1).refCount();

this.items.subscribe(x => {
console.log('ITEMS CHANGED TO:', x);
})
}

public add(itemToAdd) {
// create a function which takes state as param, returns new state with itemToAdd appended
let fn = items => items.concat(itemToAdd);
this.operationStream.next(fn);
}

public remove(itemToRemove) {
// create a function which takes state as param, returns new array with itemToRemove filtered out
let fn = items => items.filter(item => item !== itemToRemove);
this.operationStream.next(fn);
}

}

Answer

You can refer to the SO question here : How to manage state without using Subject or imperative manipulation in a simple RxJS example?. It deals with the same issue as yours, i.e. two streams to perform operations on an object.

One technique among other, is to use the scan operator and a stream of operations which operates on the state kept in the scan but anyways go have a look at the links, it is very formative. This should allow you to make up some code. If that code does not work the way you want, you can come back and ask a question again here with your sample code.