如何使观察者返回可观察状态?

Sam*_*Sam 6 rxjs firebase firebase-authentication

我是rxjs的新手,希望就如何解决此问题提供帮助。

我想传递一个Observerto onAuthStateChanged(),它接受一个观察者对象。观察者将做一些工作并发出一个布尔值,以便可以将布尔值作为返回Observable。我该如何实现从可观察到观察者的桥梁?

export class AuthGuard implements CanActivate {

constructor(private firebase: FirebaseService, private router: Router) {
}

canActivate(): Observable<boolean> {
    this.firebase.auth.onAuthStateChanged(/* an observer */)
    return /* an Observable<boolean> */
    }
}
Run Code Online (Sandbox Code Playgroud)

Dor*_*rus 5

由于onAuthStateChanged将观察者作为输入,并返回拆卸函数,我们可以简单地将其包装为:

Rx.Observable.create(obs => firebase.auth().onAuthStateChanged(obs))

实际上,出于奇怪的原因,这可能不起作用,我们可以这样做:

var onAuthStateChanged$ = Rx.Observable.create(obs => {
  return firebase.auth().onAuthStateChanged(
    user => obs.next(user),
    err => obs.error(err),
    () => obs.complete());
})
Run Code Online (Sandbox Code Playgroud)

现在,如果您不熟悉该Observable.create函数,让我解释一下:create接受一个onSubscribe函数,该函数传入观察者并返回拆卸函数。这听起来是不是很熟悉现在onAuthStateChanged正在建立?你交出来nextOrObserver,它会返回拆解!

(现在由于奇怪的原因nextOrObserver不接受observer我,所以我转而给它一个next函数。Hench 上面的代码。)

随着onAuthStateChanged$成立,我们可以使用将流运营商。所有操作符所做的就是将一个 observable 转换为另一个,而 RxJs 有几十个这样的。在您的情况下,它可能如下所示:

canActivate(): Observable<boolean> {
  onAuthStateChanged$
    .do(user => {if (!user) { this.router.navigate(['/login']); } })
    .map(user => !!user)
    .do(user => console.log('Authenticated?', user))
}
Run Code Online (Sandbox Code Playgroud)


Sam*_*Sam 4

为了造福他人,这就是我最终写的内容,看起来效果不错。

import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';

import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { FirebaseService } from '../shared/firebase.service';


@Injectable()
export class AuthGuard implements CanActivate {

    loggedInSubject: ReplaySubject<any>;

    constructor(private firebase: FirebaseService, private router: Router) {
        this.loggedInSubject = new ReplaySubject(1);
        this.firebase.auth.onAuthStateChanged(this.loggedInSubject);
    }

    canActivate(): Observable<boolean> {
        return this.loggedInSubject.map(user => {
            if (!user) {
                this.router.navigate(['/login']);
            }
            console.log('Authenticated?', !!user);
            return !!user;
        }).take(1);
    }

}
Run Code Online (Sandbox Code Playgroud)