我在订阅一个在不同组件中调用的观察者时遇到了问题。
我的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中的用户,并且在单击注销按钮时应该取消设置。
答案 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>