18

Can someone help to convert this promise to an RxJs observable? I want to get token from local storage and if error,it should be catched with observer that subscribed to observable. Below is existing solution with Promise:

  getToken(): Promise<any> {
    return new Promise<any>((resolve, reject) => {
      resolve(JSON.parse(localStorage.getItem('currentUser')).token);
      reject();
    });
  }

and subscriber is :

 this.authService.getToken().then(token => {
      this.token = token;
    }).catch(() => console.log('Error! cannot get token'));

I tried to convert it to Observable with below method :

 getToken2(): Rx.Observable<number> {
    return Rx.Observable.create(obs => {
      obs.next(JSON.parse(localStorage.getItem('currentUser')).token);
       obs.error('Error! cannot get token');
    });
  }

and

  this.authService.getToken2()
  .subscribe((token) => console.log(token), (er) => console.log(er));

But the problem is that when error occurs while getting token from localstorage ,the RxJs observable does not catch it via obs.next().It is like it is resolved successfully.Whereas Promise catches it successfully via reject method.Can someone give an idea what is wrong? Thanks

Vugar Abdullayev
  • 1,852
  • 3
  • 21
  • 46

2 Answers2

26

You don't need to do all this, just use from():

import { from } from 'rxjs';

from(this.authService.getToken())
  ...
  .subscribe(...)

If you want to use a Promise anywhere in an Observable chain you don't even need to convert it to Observable as it happens automatically.

https://medium.com/@benlesh/rxjs-observable-interop-with-promises-and-async-await-bebb05306875

Apr 2019: Updated for RxJS 6

martin
  • 93,354
  • 25
  • 191
  • 226
  • 1
    Thank you Martin for answer.I But I want to convert getToken method itself to Observable. I do not want to use Promise or fromPromise. Can you write that please. – Vugar Abdullayev Sep 11 '17 at 09:23
  • I don't understand what you want to do. You don't want to be using Promises at all or what? Can you make a demo showing what you want to do? – martin Sep 11 '17 at 09:31
  • Exactly. I do not want to use Promise at all. Firstly want to write getToken with Observable rather than converting with fromPromise. Then subscribe to this method. – Vugar Abdullayev Sep 11 '17 at 09:45
  • If you think `catch` doesn't work as you expect make a demo. – martin Sep 11 '17 at 09:55
  • getToken2 works successfull but when token not retrieved ,obs.error() does not emit error so unable to catch error in subscriber. I debugged and realized that application resolves obs.next successfully(always) so does not implement obs.error(). Can you please tell what is wrong? – Vugar Abdullayev Sep 11 '17 at 10:00
  • `obs.error()` does emit an error and `catch` handles only `error` emissions. The problem will be somewhere else in your code. – martin Sep 11 '17 at 10:14
  • it works now. I just rebuilded project. Do not know why was not working before. Thank you for help! – Vugar Abdullayev Sep 11 '17 at 10:17
2

Your getToken()-Method should have some proper error-handling. Calling both resolve() and reject() is bad and could lead to unexpected behaviour. Better do something like this:

getToken(): Promise<any> {
  return new Promise<any>((resolve, reject) => {
    try {
      resolve(JSON.parse(localStorage.getItem('currentUser')).token);
    catch(err) {
      reject(err);
    }
  });
}

Having said that getToken2() should have proper error-handling as well, e.g.:

getToken2(): Rx.Observable<number> {
  return Rx.Observable.create(obs => {
    try {
      obs.next(JSON.parse(localStorage.getItem('currentUser')).token);
    catch(err) {
      obs.error(err);
    }
  });
}
smoebody
  • 642
  • 7
  • 12