与其他组件或服务共享可观察量

时间:2017-08-10 16:32:52

标签: angular rxjs observable

我在订阅一个在不同组件中调用的观察者时遇到了问题。

我的Angular 4应用程序有一个导航栏,其中包含一些用户信息。在登录时从对服务器的http请求获得用户信息。这是使用LoginService管理的。在注销时,我们将用户设置为null。

logIn() {
  return this.http
  .get(this.apiUrl)
  .map(response => response.json())
}

logOut() {
  return Observable.of(null)
}

从登录组件中,使用该服务获取用户详细信息非常容易。

logIn() {
  this.loginService.logIn().subscribe((user) => {
    console.log('Logged in')
    this.user = user
    console.log(this.user)
  )
}

但我还需要从另一个组件中获取它们以设置导航栏中的值。我想我需要使用navbar组件订阅LoginService logIn()和logOut()函数,合并这些observable,如果它们中的任何一个触发事件,则更新用户。但我无法订阅他们,2天后我仍然坚持这个。

I've made a plunk to show the problem。单击登录按钮时,应该设置app.component中的用户,并且在单击注销按钮时应该取消设置。

2 个答案:

答案 0 :(得分:3)

我只是使用BehaviorSubject而不是将用户保留为LoginService中的属性。然后,您可以在需要当前用户时订阅它。然后注销只是调用.next(null)

见到你更新的plnkr:https://plnkr.co/edit/soeqH4IiNhcanNqxdnLS?p=preview

login服务

@Injectable()
export class LoginService {
  private apiUrl = 'https://api.github.com/users/geraintanderson'

  user$ = new BehaviorSubject(null);

  constructor(
    private http: Http
  ) {}

  logIn() {
    return this.http
      .get(this.apiUrl)
      .map(response => response.json())
      .do(user => this.user$.next(user))
  }

  logOut() {
    this.user$.next(null);
  }
}

模板:

<span *ngIf="loginService.user$ | async; else noUser; let user">
  Logged in as <b>{{ user.name }}</b>
</span>
<ng-template #noUser><span>Not logged in</span></ng-template>

答案 1 :(得分:1)

更简单的解决方案是不公开可观察对象,而只是暴露数据。我在这里更新了你的plunker:https://plnkr.co/edit/ilfEtmxolC16vRKRiE0q?p=preview

服务:

import { Injectable } from '@angular/core'
import { Http } from '@angular/http'

import 'rxjs/add/operator/map'

@Injectable()
export class LoginService {
  user;

  private apiUrl = 'https://api.github.com/users/geraintanderson'

  constructor(
    private http: Http
  ) {}

  logIn() {
    return this.http
    .get(this.apiUrl)
    .map(response => response.json())
    .subscribe((user) => {
      console.log('Logged in')
      this.user = user
      console.log(JSON.stringify(this.user));
    )
  }

  logOut() {
    this.user = null;
    console.log('Logged out')
  }
}

组件:

import {Component, OnInit, VERSION} from '@angular/core'
import { LoginService } from './login.service'

@Component({
  selector: 'my-app',
  templateUrl: './src/app.component.html',
})
export class App implements OnInit {
  get user() {
    return this.loginService.user;
  }

  constructor(private loginService: LoginService) {
    this.angularVersion = `Angular version ${VERSION.full}`
  }
}

html:

<div>
  <span *ngIf="user">Logged in as <b>{{user.name}}</b></span>
  <span *ngIf="!user">Not logged in</span>
  <h2>Shared services</h2><p>Created with {{angularVersion}}</p>
  <hr>
  <app-login></app-login>
</div>