RxJS Observable &观察者问题 [英] RxJS Observable & Observer issues

查看:39
本文介绍了RxJS Observable &观察者问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an Angular 2 service that executes a few steps to authenticate and log in an app user. Any time I try to call next() on my Observer I get an error that it is undefined. The only place I can successfully call next() on it is inside contructor when the Observable is instantiated.

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

If I call authenticateUser() I get an error that this.isLoggedIn is undefined.

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);});

};

推荐答案

如果你想在 Observable 实例化之外的 Observer 上调用 .next(),你应该使用 Subject 而不是而不是单独的 Observables 和 Observers.主体同时充当两者.您可以从向其传递事件的位置分别订阅它们.

If you want to call .next() on an Observer outside of the instantiation of the Observable, you should use a Subject rather than separate Observables and Observers. Subjects act as both. You can subscribe to them separately from where you pass events to it.

有不同种类的主题,但对于您的情况,我会推荐一个 BehaviorSubject.每当您订阅它时,它不仅会捕获未来的事件,还会返回订阅发生之前触发的 last 事件.这对于身份验证组件很有用,因为您不必为成功登录编写单独的代码,也不必在用户已经发生身份验证(或稍后注销)后实际检查用户是否已通过身份验证.这也很简单.

There are different kinds of Subjects, but for your situation, I would recommended a BehaviorSubject. Whenever you subscribe to it, not only will it catch future events, it will return the last event fired before the subscription happened. This is useful for an authentication component because you won't have to write separate code for a successful log in and actually checking if a user is authenticated after it has already happened (or a later sign out). It's really simple too.

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() 之前还是之后发生都无关紧要.

All you need to do wherever you want to check for log in status is grab the BehaviorSubject and subscribe to it. It doesn't matter whether or not the subscription happens before or after doLogin() was called.

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

If you intend to preserve the login state on refresh, all you'd need to do in the constructor is check for authentication and call the .next(true) on the BehaviorSubject as usual.

另见:

ReactiveX 主题文档

Rx BehaviorSubjects 简介

这篇关于RxJS Observable &amp;观察者问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆