Angular: Should I subscribe() to http.get() each time I need to update?

非 Y 不嫁゛ 提交于 2019-12-11 19:06:29

问题


I wonder if I am using Observable.subscribe() too many times or not.

In my component class, I have a function loadData(). It calls another function this.service.getData() that uses HttpClient.get() to perform a HTTP request to the server.

Currently in my function loadData(), I subscribe to the result of this.service.getData().

Each time the user clicks on a "Update" button, I would like to call my function loadData().

The question

  • If I call my function loadData() every time I need to perform HTTP request, will I create as many subscribers?
  • Is there a risk of memory leaks?
  • If so, do you know how I should refactor my code?

The answer

  • I found this other post Is it necessary to unsubscribe from observables created by Http methods?
  • It explains that the Angular code actually call observable.complete () after an HTTP request, with a delay
  • So I modified my code below to check that fact and the tests confirmed that it was true

Samples of code

private loadData() {
    this.loading = true;
     const subscription = this.service.getData()
      .pipe(
  // console.log() with a delay added for test - START
  map(val => {
    window.setTimeout(() => {
      // This will print true.
      console.log('After delay: Is Subscriber closed?', subscription.closed);
    }, 10);
    return val;
  }),
    // console.log() with a delay added for test - END
    takeUntil(this.ngUnsubscribe))
      .subscribe(data => {
        this.data = data;
        // This will print false.
        console.log('Is Subscriber closed?', subscription.closed);
      },
      error => {
        console.error(error);
        throw error;
      },
      () => {
        this.loading = false;
      });
}
getData(): Observable<DataObject> {
    const uri = encodeURI(this.configService.getUri());
    const headers = new HttpHeaders();
    if (this.pipelineEtag) {
      headers.set('If-None-Match', this.pipelineEtag);
    }
    return this.http.get(uri, {
      headers: headers,
      observe: 'response'
    }).pipe(
      map(resp => this.processResponse(resp)),
      catchError(error => this.handleError(error, this.envProduction))
    );
}

回答1:


each time the HTTP Call returns a value, the Observable completes. so it is safe to do something like this in the Service

loadData() { 

    return this.http.get<Data>(dataUrl).pipe(
      //  tap(data => console.log(data)), // eyeball results in the console
      catchError(err => this.handleError(err))
    );

}

and then call

this.service.loadData().subscribe((data:Data) => do somthing)

you can even call exhaustMap or switchMap to control the Observable flow, in order to don't "hint" too many time the server




回答2:


This is the correct usage, and there is no risk in creating multiple subscribers.

From the documentation:

The AsyncPipe subscribes (and unsubscribes) for you automatically.

Source


The technical detail is that once the Http request is completed, the observable's .complete method is called which kills all current subscribers. This means that your subscribers are created, used, and the immediately discarded.




回答3:


So in the end

  • I found this other post : Is it necessary to unsubscribe from observables created by Http methods?
  • It explains that the Angular code actually call observable.complete () after an HTTP request, with a delay
  • So I modified my code below to check that fact and the tests confirmed that it was true


来源:https://stackoverflow.com/questions/52223727/angular-should-i-subscribe-to-http-get-each-time-i-need-to-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!