RxJS Observable&观察员问题

时间:2016-08-15 19:37:52

标签: angular rxjs rxjs5

我有一个Angular 2服务,它执行几个步骤来验证和登录app用户。每当我尝试在我的Observer上调用next()时,我都会收到一个未定义的错误。我可以成功调用next()的唯一地方是在实例化Observable时的构造函数内部。

如果我调用authenticateUser(),我收到一个错误,即this.isLoggedIn未定义。

AuthService.ts

public isLoggedIn$: Observable<boolean>;
private isLoggedIn: Observer<boolean>;

constructor(...) {

    this.isLoggedIn$ = new Observable<boolean>(
        (observer: Observer<boolean>) => {
            this.isLoggedIn = observer;

            // this works fine
            this.doLogin();

        }).share()

}

private doLogin = ():void => {

    let context:AuthContextModel = this.authContextService.getAuthContext();

    if (context) {

        let isAuthenticated = this.isAuthenticated(context);

        if (isAuthenticated) {

            this.doCreateCurrentUserContext(context)
                .then((result) => {return this.doNotifyLoggedInStatus(result);});
        }
    }
};


private doNotifyLoggedInStatus = (result:boolean):Promise<boolean> => {

    this.isLoggedIn.next(result);

    return new Promise((resolve, reject) => {
        return resolve(true);
    });
};


public authenticateUser = (user: string, pass: string):Promise<boolean> => {
    return this.doFetchToken(user, pass)
        .then((fetchTokenData) => {return this.doStoreToken(fetchTokenData);})
        .then((authContext) => {return this.doCreateCurrentUserContext(authContext);})
        .then((result) => {return this.doNotifyLoggedInStatus(result);});

};

1 个答案:

答案 0 :(得分:3)

如果要在Observable实例化之外的Observer上调用.next(),则应使用Subject而不是单独的Observables和Observers。主体充当两者。您可以将活动传递给它的地方单独订阅。

有不同类型的主题,但根据您的情况,我建议使用BehaviorSubject。无论何时订阅它,它不仅会捕获未来的事件,它还会返回在订阅发生之前触发的 last 事件。这对于身份验证组件非常有用,因为您不必为成功登录编写单独的代码,并且实际检查用户是否已经过身份验证(或稍后注销)。它也很简单。

import { BehaviorSubject } from 'rxjs/Rx'; 

//...
  public isLoggedIn: BehaviorSubject<boolean> = BehaviorSubject.create();

  constructor(...) { }

  private doLogin():void {

    //... Do the log in
    this.isLoggedIn.next(true);

  };

您需要检查登录状态的所有内容是获取BehaviorSubject并订阅它。订阅是否在调用doLogin()之前或之后发生并不重要。

如果您打算在刷新时保留登录状态,那么您在构造函数中需要做的就是检查身份验证并像往常一样调用BehaviorSubject上的.next(true)

另见:

ReactiveX Subject docs

Intro to Rx BehaviorSubjects