Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rxjs observable.pipe(take(1)) vs toPromise

Recently I've been moved to a new project which uses angular 6 as frontend framework and spring for REST services.

The project is in development for 2 years now and what I've observed was that almost all HTTP request made with angular HttpClient is then piped to take filter from rxjs. All REST APIs emit only one value. There's no need for manual cancellation and the laziness property of observables.

My intuition is that using toPromise() would be a better way to code.

What are your thoughts?

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() {
     return http.get('/customers');
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().pipe(take(1)).subscribe((customers) => {
           //do some stuff
      })
  }

My proposed approach:

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() : Promise<Array<Customer>> {
     return http.get('/customers').toPromise();
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().then((customers: Array<Customer>) => {
         //do some stuff
      })
  }

I think that my approach is better because it is strongly typed and it's cleaner.

like image 828
George Tarida Avatar asked May 29 '19 10:05

George Tarida


People also ask

Why is toPromise deprecated?

As mentioned here, these are the main reasons why toPromise is being deprecated: One goal was to remove it from the Observable prototype and turn it into a standalone util function. The naming of toPromise is not the best. Especially when used in combination with await it does not read very well: await categories$.

How do you use toPromise?

toPromise method is Promise object. In order to use async/await style, you need at first wrap your code with async function, by prepending async keyword to function, and then with await keyword tell your code to wait for async operation. In your case it's http request.

What does pipe () do RxJS?

pipe() can be called on one or more functions, each of which can take one argument ("UnaryFunction") and uses it to return a value. It returns a function that takes one argument, passes it to the first UnaryFunction, and then passes the result to the next one, passes that result to the next one, and so on.

Which is better Promise or Observable?

Often Observable is preferred over Promise because it provides the features of Promise and more. With Observable it doesn't matter if you want to handle 0, 1, or multiple events. You can utilize the same API in each case. Observable also has the advantage over Promise to be cancellable.


2 Answers

Actually the accepted answer is misleading by saying that transforming an observable to a promise is like taking a step backward. Rather it's about what your needs are. as stated in Angular Documentation:

Observables differentiate between chaining and subscription. Promises only have .then() clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.

And the difference between toPromise() and take(1) (or for short use operator first()), is that take(1) completes after the 1st value emitted, while toPromise waits for the last emitted value (waits for the observable to complete then resolves the last value emitted).

Another difference between observables and promises that might interest you, is that Observable subscriptions are cancellable while promises are not. As a concrete example, say your API /customers takes time but you dont need the results anymore and you navigate to another page, unsubscribing cancels the HTTP request.

like image 56
Abdessamad ABOUKDIR Avatar answered Sep 23 '22 00:09

Abdessamad ABOUKDIR


As you mentioned strongly typed we can do the same in observable approach.


public getCustomers():Observable<Array<Customer>>  {
     return http.get<Array<Customer>>('/customers');
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers()
      .pipe(take(1))
      .subscribe((customers: Array<Customer>) => {
       //do some stuff
       });
  }

  • For HttpRequest with single HttpResponse you may rely on promise approach.
  • But HttpRequest with multiple response such as progress/stream of data(blob) go for the Observable approach.

Try to use Observable as much as possible, once you familiar with you wont go for other options. So Give it a try!

like image 39
Veeraragavan Avatar answered Sep 21 '22 00:09

Veeraragavan