Transforming Observables in RxJava and RxScala - rx-scala

I have an Observable that emits a List of entries as below:
val obsList: Observable[List[MyEntry] = Observable.from(getListEntry)
// getListEntry would give me a List[MyEntry]
How could I now get the contents piped into another Observable that takes in a MyEntry? I mean, for each entry in the original Observable, I would need to pipe them to another Observable that has a type signature of:
Observable[MyEntry]

I figured out how to do this! I'm using the Monifu library!
So, I would be doing:
Observable.fromIterable(listOfEntry)

Related

Rxjs await Observable complete

I’d like to await the completion of my observable. It has a takeUntil I receive a value emited from my cancel$ observable. Its possible that cancel$ emits a valeu befor observable1 even emits its first value. That will give me an error.
await lastValueFrom(observable1.pipe(takeUntil(cancel$)))
console.log("myObservable is completed");
I found that using the deprecated await observable1.toPromise() fixes my problem. But I'd like to avoid something deprecated.
Ok, I finally found my answer here : .toPromise() and lastValueFrom() in rxjs
lastValueFrom takes a second parameter where you can define a default value when nothing has been emitted.

RxJS: Second observable's input argument depends on first observable's output

I have two observables
baseObs$ = serviceCall(); // this return Observable<Foo>
secondObs$ = serviceCall(args); // this return Observable<Bar>
args in this example is public variable defined somewhere else. It doesn't need to be though if that makes this easier.
baseObs I can call whenever I want, but secondObs I can only call after baseObs is succesfully called and handled (don't know the right words so example follows):
I have now something like
baseObs$.subscribe(x => {
const args = x.args; // just example. Point is, I need x to build args.
serviceCall(args).subscribe(y => {
console.log(y); // This is fine
});
});
This suits my needs but I got feedback that no subscribe should live inside another subscribe. How would you achieve same thing using baseObs$ and secondObs$ defined above?
PS. All is pseudo code but hopefully I didn't do too much typos. I think the idea should be clear though.
In the simple case that the first observable only emits once (like a typical HTTP request), any one of switchMap, mergeMap etc. will do:
serviceCall().pipe(
switchMap(x => serviceCall(x.args))
).subscribe(console.log);
If that assumption is not true, you're going to want to read their respective documentation to understand how behavior will change between them. In fact, I'd recommend reading up on them to know their differences even just in general, as it's very valuable information when dealing with reactive code.

Unable to understand this code involving BehaviorSubject and Observables

I am reading this piece of code
https://coryrylan.com/blog/angular-observable-data-services
esp this line
this._todos.next(Object.assign({}, this.dataStore).todos);
What i don't understand is why after the call to
Object.assign({}, this.dataStore ) which copies the contents of the datastore to an new object why not do just
this._todos.next(Object.assign({}, this.dataStore))
instead of
this._todos.next(Object.assign({}, this.dataStore).todos)
Any ideas ?
Because it is good practice to expose only the data that a component requires to that component.
The following line causes the _todos Subject to only emit the Todos data:
this._todos.next(Object.assign({}, this.dataStore).todos)
The code below, which you suggest, would cause the _todos subject to emit the entire dataStore:
this._todos.next(Object.assign({}, this.dataStore))

shareReplay vs ReplaySubject - only ReplaySubject caches latest value before subscription

I have an external hot source pushing values before observers can subscribe. Upon subscription, the late observers should receive the latest value and every value from that point on. For this, I used the following code (the relevant line is marked with '<<<', the s Subject is here just to be able to create the simplest sample possible, in reality the hot source works differently):
// irrelevant, just to send values
const s = new Subject();
// make the observable cache the last value
const o = s.pipe(shareReplay(1)); // <<<
// now, before subscription, values start coming in
s.next(1);
s.next(2);
s.next(3);
o.subscribe(n => console.warn('!!!', n));
This doesn't work (I expected it to print !!! 3 but nothing happens), but I found a way to make it work:
// irrelevant, just to send values
const s = new Subject();
const r = new ReplaySubject(1);
s.subscribe(r);
const o = r.asObservable();
s.next(1);
s.next(2);
s.next(3);
o.subscribe(n => console.warn('!!!', n));
i.e instead of using shareReplay(1), I create a ReplaySubject(1) and use it as a bridge. With this code, I do get the coveted !!! 3.
While I'm happy it works, I would like to understand why the first snippet doesn't. I always thought shareReplay is pretty much equivalent to the second way and actually kind of implemented this way. What am I missing?
When you use s.pipe(shareReplay(1)) you're just adding an operator to the chain (like changing the chain's prototype). But there's no subscription and shareReplay doesn't subscribe to its source when it itself doesn't have any observers. So it's not caching anything because there's no subscription to source Observable even when source is "hot".
However, when you use s.subscribe(r) you're regularly making a subscription to s so r starts receiving items and ReplaySubject will be caching them.

rxjs switch unwrapping observable

I setup a subject and then put some methods on it. It seems to work as intended until it gets to .switch() which I thought would simply keep track of the last call. I get the error Property 'subscribe' does not exist on type 'ApiChange' It seems to convert it to type ApiChange from an observable. I don't understand this behavior. Should I be using a different operator?
Service:
private apiChange = new Subject<ApiChange>();
apiChange$ = this.apiChange.asObservable().distinctUntilChanged().debounceTime(1000).switch();
Component:
this.service.apiChange$.subscribe(change => {
this.service.method(change);
});
.debounceTime(1000) will already assure you will only get a maximum of one value emitted from your observable chain per second. All the values preceding the 1 second quiet time will already be discarded.
With a simple Subject (not a ReplaySubject), past values are not provided to subscribers anyway.
You probably just want to skip the .switch() and enjoy the chain without it.

Resources