Let's download a list of my repositories and print the ones starting with the letter "A". See how we have no ngOnInit, because the async pipe
render "triggers a subscription".
Since the response is one array with lot's of objects, we use map
in the pipe and not filter
.
In a "real" angular app we would use the angular's http service in our own service.
import {Component} from '@angular/core';
import {ajax} from 'rxjs/ajax';
import {map} from 'rxjs/operators';
import {Observable} from 'rxjs';
interface IRepo { name: string; id: number; }
@Component({
selector: 'app-github-repos',
template: `
<ul>
<li *ngFor="let repo of repos$ | async">{{ repo.name }}</li>
</ul>
`
})
export class GithubReposComponent {
repos$: Observable<IRepo[]>;
constructor() {
this.repos$ = ajax.getJSON('https://api.github.com/users/szkrd/repos')
.pipe(map((repos: IRepo[]) => repos.filter(repo => /^a.*/.test(repo.name))));
}
}
Get JSON from url-1, then use a value from that response to download data from url-2.
ajax.getJSON(url('/movie/top_rated')).pipe(
tap((data: any) => console.log('Number of top rated items:', data.results.length)),
map((data: any) => data.results[0]),
tap((data: any) => console.log('Selected first movie:', data.id, data.title)),
// "switch to a new observable"
switchMap((data: any) => ajax.getJSON(url(`/movie/${data.id}`)))
)
Here the observable returns responses as they arrive:
const urls: string[] = ids.map(id => url(`/movie/${id}`));
const concurrentCalls = 5;
return from(urls).pipe(
mergeMap(ajax.getJSON, concurrentCalls)
);
Similar to Promise.all
, download two jsons and then convert the array into a nicer object:
zip(
ajax.getJSON(url('/movie/top_rated')),
ajax.getJSON(url('/discover/movie'))
).pipe(
map(([topRated, discovered]: any[]) => ({
topRated: topRated.results,
discovered: discovered.results
})),
);
Just like Promise.all, this will fail if any of the calls fails. To continue even then, add an error handler:
const onError = (err: any) => { console.error(err); return of(err); };
return zip(
ajax.getJSON(url('/movie/top_rated')).pipe(catchError(onError)),
ajax.getJSON(url('/discover/movie')).pipe(catchError(onError)),
)//.pipe(...
Add two numbers (a$ and b$) using the two observables' latest value:combineLatest
will create an array [a, b]
then we pipe & map that to arr[0] + arr[1]
@Component({
selector: 'app-add',
template: `
<p>
<label>A <input type="number" (change)="updateA($event)" [value]="a$ | async"></label>
+
<label>B <input type="number" (change)="updateB($event)" [value]="b$ | async"></label>
= {{sum$ | async}}
</p>
`
})
export class AddComponent {
a$ = new BehaviorSubject(-10);
b$ = new BehaviorSubject(10);
sum$ = combineLatest(this.a$, this.b$).pipe(map(x => x[0] + x[1]));
updateA($event) { this.a$.next(parseInt($event.target.value, 10)); }
updateB($event) { this.b$.next(parseInt($event.target.value, 10)); }
}