Let's say I'd like to retrieve a set of records from a store, display them in a list using *ngFor
, e.g.
<ul>
<li *ngFor="let record in records | async">
...
</li>
</ul>
Now the user clicks the 'New...' button, another record is added to the store and
recordAdded: EventEmitter<string>;
fires to tell me about the location. So I get that new record - and that record only - from the store and... whoops, how do I get my *ngFor
to display this additional record?
Ok, so I could keep all records in array, for example
_records: Record[];
and fill this array by subscribing to the Observable<Record[]>
like
this.recordService.getAll().subscribe(r => this._records = r);
But this array needs to be an Observable
itself in order to notify consumers when there is a new record. So
observableRecords = Observable.create(obs => {
this.recordService.getAll().subscribe(rec => {
this._records = rec;
obs.next(rec);
// Got the array published, now waiting for events
this.recordAdded.subscribe(rec => {
this._records.push(rec);
obs.next(this._records);
});
});
});
Ugh... Not only is this excruciating to look at, there's also a ton of overhead as the whole array gets re-published every time a new record is added and - most likely - Angular 2 will re-build the whole list from scratch at every turn.
Since this is such a common scenario I imagine there must be a much better way to do this.
For example, RxJS is a famous library that provides Observables support. Let’s see what is Observables in Angular and how to create Observables in Angular. The Observable is just a function with minimal distinctive characteristics.
Reactive Extensions for JavaScript, or RxJS, is a JavaScript library that uses observables for reactive programming. It can be used with other JavaScript libraries and frameworks, and it integrates well into Angular. Today, we will discuss RxJS and Angular, the benefits of using RxJS in Angular, and how to use them together.
You can import it from the ‘rxjs’ library The Create method is one of the easiest. The create method calls the observable constructor behind the scene. Create is a method of the observable object, Hence you do not have to import it.
The From Operate tries to iterate anything that passed into it and creates an observable out of it. There are many other operators or methods available in the RxJS library to create and manipulate the Angular Observable. We will learn a few of them in the next few tutorials
yeah, there certainly is - you need to use flatmap
flatmap is the way to go whenever you find yourself subscribing within a subscribe.
You've got a stream of streams (a metastream) and you need to flatten it - then you will be able to subscribe once to the flattened stream (avoiding the nested subscribe).
read the tutorial until the bit where it introduces you to flatmap.
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
Here's some code to kick you off ...
public tagsTextStream = this.tagsTextSubject.asObservable().flatMap((q:string) => {
// noinspection UnnecessaryLocalVariableJS
let restStream = this.restQueryService.getTagsList(q)
.map((tags:any) => {
// filter out any tags that already exist on the document
let allTags = _.map(tags, 'name');
let documentTags = _.map(this.tags, 'name');
return _.pull(allTags, ...documentTags);
})
.catch((err:any) => {
return Observable.throw(err);
});
return restStream;
}).publish().refCount();
Don't forget ... .publish().refCount()
or you end up with multiple requests and stuff.
read more about it all on the link i sent.
PS
In the code above, q is the values being emitted from the initial observable. Be advised that the terms observable and stream are interchangeable, they are the same thing. observable is just describing a stream you can subscribe to. Hence, reactive programming (Rx). You are reacting to events coming from the stream.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With