ToastedSoul
ToastedSoul

Reputation: 1296

How to correctly use Observable and Angular async pipe?

I tried using the Angular async pipe and got it working to display the time I get from the server using a http get request. I have the following questions:


Angular component:

    @Component({
      selector: 'app-async-test',
      templateUrl: './async-test.component.html',
      styleUrls: ['./async-test.component.scss']
    })
    export class AsyncTestComponent implements OnInit {
      private readonly baseApiUrl = environment.baseApiUrl;
      httpServerRequest$ = this.http.get<ServerTimeViewModel>(`${this.baseApiUrl}/admin/servertime`);
    
      testNormalResult: Date = null;
      testAsyncResult$: Observable<Date> = null;
      
      constructor(
        private http: HttpClient
      ) {}
    
      ngOnInit() {
          this.testAsync();
      }
    
      testNormal(): void {
        this.httpServerRequest$.subscribe(data => {
            this.testNormalResult = data.serverTime;
          });
      }
    
      testAsync(): void {   
        this.testAsyncResult$ = this.httpServerRequest$
          .map(d => d.serverTime);
      }
    }

ServerTimeViewModel class:

    export class ServerTimeViewModel {
      serverTime: Date;
    }

template:

    Test normal: {{ testNormalResult | date:'mediumTime'}}<br>
    Test async: {{ testAsyncResult$ | async | date:'mediumTime'}}<br>  
    <button type="button" (click)="testNormal()">test normal</button>
    <button type="button" (click)="testAsync()">test async</button>

Upvotes: 2

Views: 5345

Answers (3)

ToastedSoul
ToastedSoul

Reputation: 1296

The answer here https://stackoverflow.com/a/41554338/54159 helped me a lot. The solution was to use a ReplaySubject. Now refreshing from the web service does not result in any flickering anymore.

I've put it all in a data service. My component binds directly to dataService.person$ and calls dataService.fetchRandomPerson(x) to execute a new http get request.

Here's the DataService:

    @Injectable()
    export class DataService {
      private readonly baseApiUrl = 'https://swapi.co/api';
    
      private personSubject = new ReplaySubject<Person>(1);
      person$: Observable<Person> = this.personSubject.asObservable();
    
      constructor(
        private http: HttpClient
      ) { }
    
      fetchRandomPerson(personId: number): void {
        // re-execute http get
        // https://stackoverflow.com/a/41554338/54159
        this.http.get<Person>(`${this.baseApiUrl}/people/${personId}/`)
          .subscribe(res => this.personSubject.next(res));
        
        // note: no need to unsubscribe from http requests
        // https://stackoverflow.com/a/35043309/54159
      }
    }

Here's a running version: https://stackblitz.com/edit/angular-dpbe7t

Upvotes: 2

Luillyfe
Luillyfe

Reputation: 6872

1. If you want to re-execute the http get request again to get updated data, is it correct to do what I'm doing in testAsync(), or is there a more elegant way to do this?

You are getting an Observable (not a Promise) with this in mind, you do not need to "re-execute the http request to get the new data", that data is coming to you as soon it gets on your server (or whatever is you source data), that the purpose of an Observable (be observed and watched fro changes).

2. Also I noticed some flickering going on when using the async pipe and re-requesting the data. This does not happen in the non-async version ("testNormal()"). Is there any way to prevent this from happening?

That is the point of using an Observable, There are Observers (Ex: functions) always watching the data changes on your source data. If you want to change this, you could use a Promise instead (You can still use Promises on Angular). Also you if want to limit your response you can use the take operator, there are also more of them just check them out.

Upvotes: 0

Krishna Mohan
Krishna Mohan

Reputation: 1732

Regarding your second question, to remove the flickering you should cache the server response. You can find more details in the angular guide.

Upvotes: 0

Related Questions