15

I have an auth guard that needs an asynchronous response true/false when the site is visited and the user is already logged in.

I'm using Firebase's onAuthStateChanged (link to docs) and it uses a callback function. How can I turn my isLoggedIn() method into something that can return Observable<boolean>?

Typscript:

get isLoggedIn(): Observable<boolean> {

    // want something like this:
    return Observable.fromCallback(firebase.auth().onAuthStateChanged).map(user => !!user);

    // this returns () => boolean, but I need a promise or observable
    return firebase
      .auth()
      .onAuthStateChanged((user) => {
        return !!user;
      });

}
Nick Jonas
  • 1,197
  • 4
  • 13
  • 24

3 Answers3

26

You can do it like this.

get isLoggedIn(): Observable<boolean> {

  // want something like this:
  return Observable.create(
    observer => firebase
        .auth()
        .onAuthStateChanged((user) => {
          observer.next(!!user)
        });
    );
}
OJ7
  • 307
  • 1
  • 2
  • 13
rohit anand
  • 286
  • 3
  • 5
  • 1
    Beware that this will add a listener with each property access/subscription and that said listener will not be removed. The arrow function passed to `create` should return the result of the `onAuthStateChanged` (which is a function that removes the listener). Doing so will see the listener removed when the observable is unsubscribed. – cartant Mar 31 '17 at 04:40
  • 1
    @cartant or rohit would you mind add an example of subscribing / unsubscribing to make this answer a bit more thorough? – Nick Jonas Mar 31 '17 at 05:13
  • `onAuthStateChanged()` returns the unsubscribe function so you just need to remove the curly braces in the subscription function when you create the Observable: `Observable.create(observer => firebase.auth().onAuthStateChanged(user => observer.next(!!user)))`. – Jaye Renzo Montejo Nov 08 '17 at 11:26
  • 5
    [bindCallback](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-bindNodeCallback) is the modern approach for the problem since RxJs 6. Checkout [these examples](https://rxjs-dev.firebaseapp.com/api/index/function/bindCallback#convert-jquery-s-getjson-to-an-observable-api). – Alex Klaus Jun 25 '19 at 01:14
15

there is one more way of doing this using bindCallback from rxjs/observable/bindCallback

const observable=bindCallback(functionWhichExpectsCallBack)

e.g

function foo(value, callback) {
  callback(value);
}
//converts callback to observable
    const observable = bindCallback(foo); 
    observable(1)
      .subscribe(console.log); 
arshid dar
  • 1,355
  • 2
  • 15
  • 23
7

Note: bindCallback and Observable.create were deprecated,
you could use new Observable instead:

...
return new Observable((subscriber) => {
  firebase
    .auth()
    .onAuthStateChanged((user) => {
      subscriber.next(user);
    })
}
am0wa
  • 7,724
  • 3
  • 38
  • 33