Rxjs: take(1) usage

2019-04-30 06:46发布

问题:

I have seen a tutorial on rxjs as like this.

My question is:
1) What is the usage of take(1) here? I see a lot of explanation online but i don't really get it. Also, i don't see any benefit of using take(1) in this code. And the author do use take(1) on every return function in REST api related service.

2) The author did not unsubscribe after subscribe. Is it because the author use take(1) therefore manual unsubscribe is not needed?

3) What if i want to implement catch function. Should i implement it before take or after take.

getProfile() { // this is a call to REST API
    return this.service.getProfile()
            .map(res => res.json())
            .take(1)
    }
}

this.data.getProfile().subscribe(profile => {
    this.userProfile = profile;
});

回答1:

The author did not unsubscribe after subscribe. Is it because the author use take(1) therefore manual unsubscribe is not needed?

Yes, that is most likely why the author uses take(1) operator. It's job is to pass one value to an observable and then unsubscribe from the source. But depending on the service it may not be required.

For example in Angular the HttpClient service completes the stream by itself after sending the final HttpResponse event value so you don't need to neither use take nor unsubscribe explicitly. Here is the sources:

@Injectable()
export class HttpXhrBackend implements HttpBackend {
  ...
  handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
    ...
    // Everything happens on Observable subscription.
    return new Observable((observer: Observer<HttpEvent<any>>) => {
      ...
      // First up is the load event, which represents a response being fully available.
      const onLoad = () => {
        ...
        if (ok) {
          // A successful response is delivered on the event stream.
          observer.next(new HttpResponse({
            body,
            headers,
            status,
            statusText,
            url: url || undefined,
          }));
          // The full body has been received and delivered, no further events
          // are possible. This request is complete.
          observer.complete();   <---------------------------------
        }

What if i want to implement catch function. Should i implement it before take or after take.

You can implement it after take since take will also transmit the error.

const stream = Observable.create((observer) => {
  observer.error(new Error());
}).take(1).catch(() => {
  return Observable.of(`An error occurred`);
}).subscribe((v) => {
  console.log(v);  // An error occurred
})