Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observable.subscribe() vs Promise with async/await [closed]

Consider the following two methods in a Service for querying a webservice:

getAssessmentById(id: number): Observable<MotorAssessorReport> {
  const url = environment.endPoints.assessment.base + 
    environment.endPoints.assessment.assessmentById + id;
  return this.httpClient.get<MotorAssessorReport>(url)
}

async getAssessmentByIdAsync(id: number): Promise<MotorAssessorReport> {
  const url = environment.endPoints.assessment.base + 
    environment.endPoints.assessment.assessmentById + id;
   const data = await this.httpClient.get<MotorAssessorReport>(url).toPromise();
  return data;
}

The first method, getAssessmentById returns an observable. The second method, getAssessmentByIdAsync, returns a promise.

subscribeToAssessment() {
 this.assessmentService.getAssessmentById(this.assessmentId).subscribe(result => 
 {
    this.assessment = result;
 });
}

async fetchAssessment() {
  this.assessment = await this.assessmentService.getAssessmentByIdAsync(this.assessmentId);
}

I have always been using the first approach, returning an Observable<T>, and subscribing in my calling code.

I recently truely began to understand that this approach should only really be used if you expect multiple results to be returned. In other words, when using a Promise<T>, the maximum amount the callback is called, is only once.

Since I have been expecting my server to only always be returning once, is my approach wrong, and should I rather be using the Promise<T> approach, combined with async/await?

like image 987
monstertjie_za Avatar asked Apr 27 '19 18:04

monstertjie_za


3 Answers

  • If you are using the service to get values continuously, use an observable.
  • If you need the data to be fetched only once, use a promise. You need to unsubscribe to an observable or else it would cause a memory leak.
  • Use async await only if necessary, in case your code creates a callback mess.
like image 155
Hari Pillai Avatar answered Oct 13 '22 11:10

Hari Pillai


I think you also have to remember the difference between hot and cold observables (see this question. Since httpClient is a cold observable, it will make the request for each call and you don't need to worry about unsubscribing afterward. The main difference between your two methods is when the http request is made. In the observable method, the request won't be made until .subscribe is called. In the promise version, the request will be made immediately. I agree with @kasperlauge that, in most cases, observables should be preferred.

like image 29
6utt3rfly Avatar answered Oct 13 '22 10:10

6utt3rfly


I would say that in most cases where you can use promises, observables can do it better! One key advantage of observables is that they can be canceled (by unsubscibing to the subscription). That is a feature which is also useful when only returning a single value.

Further more all the operator functions of observables handling multiple parallel async requests is far easier to use than to manually brew some promise handling together.

If you want to avoid unsubscribing to trivial observables/subscriptions, you can use the take(1) operator function which makes sure you do not get unexpected function call (if you forgot to unsubscribe).

This would be done as:

this.assessmentService.getAssessmentById(this.assessmentId)
 .pipe(take(1))
 .subscribe(result => 
 {
    this.assessment = result;
 });

If only simple async tasks is needed, rxjs can be unnecessary and promises can be used instead. The advantages of using promises from my perspective is the cleaner syntax using async/await and the native support (not needing to rely on a third-party library).

like image 44
kasperlauge Avatar answered Oct 13 '22 11:10

kasperlauge