观察者只接收下一次呼叫的值

时间:2016-03-24 19:19:34

标签: typescript angular rxjs

angular.io示例的启发(父级和子级通过服务进行通信)我实现了一个观察者/可观察模式,以通知我的导航组件用户是否经过身份验证。问题是导航组件仅在用户注销时收到通知。

我的身份验证服务如下:

export class AuthenticationService {

  private isAuthenticatedSource = new Subject<boolean>();

  isAuthenticated$ = this.isAuthenticatedSource.asObservable();

  constructor(private http : AuthHttp) {}

  login(email: string, password: string) {
    ...
    this.isAuthenticatedSource.next(true);
    ...
  }

  logout() {
    ...
    this.isAuthenticatedSource.next(false);
    ...
  }

}

我已确保完成两次调用(登录和注销)并且不会抛出任何错误。我的导航组件如下所示:

export class NavigationComponent implements OnDestroy, OnInit {

  private subscription: Subscription;

  isAuthenticated: boolean;

  constructor(private authService: AuthenticationService,
              private router: Router) {
    this.isAuthenticated = authService.isAuthenticated();
  }

  logout(event) {
    event.preventDefault();
    this.authService.logout();
    this.router.navigate(["Authentication", "Login"]);
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

  ngOnInit() {
    this.subscription = this.authService.isAuthenticated$.subscribe(
      value => console.log("updated to:", value)
    );
  }

}

控制台应记录&#34;更新为:true&#34;登录时和&#34;更新为:false&#34;退出时问题是它只在注销时显示一条消息。显然,观察者在登录时没有收到值(true)。希望你能帮助解释为什么会这样。

更新

现在包含对登录的调用。当用户提交(登录)表单时,从我的LoginComponent调用它。 LoginComponent看起来像:

export class LoginComponent {

  public email : string;
  public password : string;
  public errors : any;
  public next : any;

  constructor(private authService : AuthenticationService,
              private router : Router,
              private params : RouteParams) {
    // default to navigate to dashboard on successfull login
    let next = this.params.get("next") || "/Dashboard";
    this.next =  [next];
  }

  login(event) {
    event.preventDefault();
    this.authService.login(this.email, this.password)
                      .subscribe(
                        data => this.router.navigate(this.next),
                        errors => this.errors = errors);
  }

}

相应的模板只需一次登录调用:<form (submit)="login($event)">。 login不会被称为应用程序中的其他位置。

2 个答案:

答案 0 :(得分:2)

我没看到你在哪里登录。但是,我编写了一个示例,显示在UI订阅之前调用服务登录会重现您的观察,UI不会更新。请参阅AppComponent构造函数中的authService.login()调用对UI没有影响。这是因为订阅后来发生在ngOnInit中。希望这很有用。

http://plnkr.co/edit/fteTLPCJUucCVKdVzJuP

export class AppComponent implements OnDestroy, OnInit { 

  @Output subscribe: string;
  private subscription: Subscription;
  private authService: AuthenticationService;

  constructor(private authService: AuthenticationService) {
    this.subscribe = 'not set';
    this.authService = authService;

    authService.login('john', 'password'); // has no affect on UI since login happens before subscribe in ngOnInit 
  }

  login() {
    this.authService.login('john', 'password');
  }

  logout() {
    this.authService.logout();
  }

  ngOnInit() {
    this.subscription = this.authService.isAuthenticated$.subscribe(
      //value => console.log("updated to:", value)
      value => this.subscribe = '' + value;
    );
  }

}

答案 1 :(得分:0)

我并不完全确定它的工作原理,但将isAuthenticatedSource设置为静态变量可以解决问题。将不得不研究更多来了解原因。感谢您的反馈。