- Calling subscriber() without params will case an observable to fire:
this.myService.Do().subscribe();
2. When you catch a Pipe error, throw it again:
this.httpThingy.get()
.pipe(
catchError(err=> {
console.log('failed', err);
const friendlyMsg = "sorry, try again";
return throwError(friendlyMsg);
}),
map((data: ComplexMoviesTreeOfData) => data.movies.starwarsmovies)
);
3. The component can then display the error:
this.myService.Do().subscribe(
theData => (this.movies = theData),
theNiceError => this.errorMsg = theNiceError
);
4. Map operator takes the data list, then lets you choose what to actually return
map((data: ComplexMoviesTreeOfData) => data.movies.starwarsmovies)
5. asyncPipe can be a short hand for displaying data without having to subscribe and unsubscribe. Simply assign the observable from the service to a component member$ and reference it:
<div *ngFor="let movie of movies$ | async>{{movie.name}}</div>
To use this, in our component we set the member variable to the observable and of course catch the error.
this.movies$ = this.myService.Do().pipe(
catchError(err => {
this.errorMsg = err;
return [];
})
);
6. A [formControl] can be a simple observable, perhaps for a simple search box.
<input type='text' [formControl]='searchTerm' />
In your component:
searchTerm = new FormControl();
searchTerms$ : Observable<string> = this.searchTerm.valueChanges;
Now you can handle the stream of text from the searchTerms$ and react only when typing something new, and after a delay.
movies$ = this.searchTerms$.pipe(
tap(() => this.errorMsg = ''), // clear previous error
debounceTime(1000), // wait for a puse in typing
distinctUntilChanged(), // only if there was some kind of change
// Do the search if we get this far in the operators list and "switch" it to a list of movies
switchMap(searchTerm => this.movieService.search(searchTerm)
.pipe(
catchError(err=> {
this.errorMsg = err.message;
return EMPTY;
})
)
),
//If we get this far, then map the results and return what the UI expects
map(this.cleanUpResults)
);
cleanUpResults(list: movies[]) : movies[] {
return list.length === 0 ? [{title: 'No Results'}] : list;
}
7. When an error happens in an observable, it stops the stream(s). That’s bad as you can’t restart it. So we use error isolation and handle it in a sub observable where it can stop that, but not the top level one.
moviesWithErrorsIsolated$ = this.movies$.pipe(
switchMap(id=> this.getMovieById$(id)
//PIPE AGAIN off to get the movies
.pipe(
map(result => result.title), //extract title
catchError(e=> of('Didn't find it '))
)
)
);
8. Short form for calling an observable with a param
getMovies$ = theId => this.http.get<movie>(https..{theId});
9. Route object is an observable too
this.theCurrentMovie$ = this.route.paramMap.pipe(
map(params = > params.get('id')),
switchMap(id => {
return this.movieService.getMovie(id).pipe(
tap(movie => this.currentId = movie ? movie.id : 0)
);
})
);