Angular2 Observable and Promise

60,138

Solution 1

When you call subscribe(...) a Subscription is returned which doesn't have a toPromise(). If you move the code from subscribe to map you can use toPromise() instead of subscribe

return this._httpClient.post('LoginAction', credentials)
  .map(res => res.json())
  .map(user => {
    return new User(user);
  }).toPromise();

and the caller will get a Promise where he can get the value using

public login() {
    this._user = AuthService.getInstance().login(this._loginInfo)
    .then(result => {
      doSomething();
    });
}

but you get the same result if you omit `.toPromise() and the caller uses it like

public login() {
    this._user = AuthService.getInstance().login(this._loginInfo)
    .subscribe(result => {
      doSomething();
    });
}

where the only difference is subscribe() instead of then() and if the user of the library prefers the reactive style he will prefer using subscribe() like he is used to.

Solution 2

You need to import the Rx toPromise operator like

import 'rxjs/add/operator/toPromise';

Cheers!

Solution 3

From Angular2 documentation

We are advise to add this in rxjs-extension.ts

```
// Observable class extensions 
   import 'rxjs/add/observable/of'; 
   import 'rxjs/add/observable/throw';

// Observable operators 
   import 'rxjs/add/operator/catch'; 
   import 'rxjs/add/operator/debounceTime'; 
   import 'rxjs/add/operator/distinctUntilChanged'; 
   import 'rxjs/add/operator/do'; 
   import 'rxjs/add/operator/filter'; 
   import 'rxjs/add/operator/map'; 
   import 'rxjs/add/operator/switchMap'; 
```

And import it at app.module.ts (Root Module) import './rxjs-extensions';

This will help us to prevent further error.

Share:
60,138
Ned
Author by

Ned

Updated on September 28, 2020

Comments

  • Ned
    Ned over 3 years

    I started using Angular2 Observable, but I can't find something similar to .then that I used with Promises.

    This is what I want to accomplish.

    code from header.component.ts

    public login() {
        this._user = AuthService.getInstance().login(this._loginInfo);
    }
    

    code from auth.service.ts

    return this._httpClient.post('LoginAction', credentials)
      .map(res => res.json())
      .subscribe(user => {
        return new User(user);
      });
    

    With promises, login function would return Promise, that would eventually transform to actual response from server. But with Observable this won't work.

    Is there a way to do similar thing? I want to avoid need of putting subscribe inside component's login function. I want to be able to do all the work in service, and to return actual object to component.

    Also, I tried to create Promise, with toPromise, but I keep getting toPromise is not a function.

    p.s. _httpClient is my wrapper around angular2 http in which I prepare request by adding some headers etc.

    edit

    return this._httpClient.post('LoginAction', credentials)
      .map(res => res.json())
      .toPromise().    <-- i keep getting that it is not a function
      then(user => {
        return new User(user);
    });
    

    by doing this, my component will get object (which is what it need), and in service i could do additional things (like saving user to localstorage, once I logged him).

    And I switched to Promise, because doing same with Observable is not working (or I am doing it wrong)?

    I see that returned object is Observable (before calling toPromise), but I don't see toPromise function indeed.

  • smnbbrv
    smnbbrv about 8 years
    subscribe returns a Disposable and not a Subscription
  • Günter Zöchbauer
    Günter Zöchbauer about 8 years
    subscribe(observerOrNext?: PartialObserver<T> | ((value: T) => void), error?: (error: any) => void, complete?: () => void): Subscription;
  • smnbbrv
    smnbbrv about 8 years
    I don't know where you take it from, look here: github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core‌​/…
  • Günter Zöchbauer
    Günter Zöchbauer about 8 years
    github.com/ReactiveX/rxjs/blob/…. Maybe Disposable is rxjs4. Angular uses rxjs5.
  • Ned
    Ned about 8 years
    @GünterZöchbauer thanks for help. Please check my edited question, I tried to clarify it a bit more.
  • Günter Zöchbauer
    Günter Zöchbauer about 8 years
    Then you need to add import "rxjs/add/operator/toPromise";