我正在使用Angular 4,并且我的应用程序中有一个位于“player /:id”路由中的组件。当播放器从应用程序中导航到此路线时,我使用currentPlayerService同步应用程序中的当前播放器。下面的代码可以很好地工作。
this.currentPlayerService.getPlayer()
.subscribe((player) => this.currentPlayer = player);
但是,当应用程序直接从外部链接加载到“player /:id”路由时,我可以注释掉上面的内容,并使用下面的代码从路由参数中设置currentPlayer。
this.route.params.subscribe(params => {
this.playerService.getPlayer(params.id)
.subscribe((player) => {
this.currentPlayer = player;
this.currentPlayerService.setPlayer(player);
});
});
我想做的(很难找到“反应函数编程”的说法)是仅在this.currentPlayerService.getPlayer()没有加载值的情况下才从参数加载播放器。我很难构想在某种逻辑控制流中使用Observable的方法,因此可以提供任何帮助。
谢谢!
最佳答案
可观察对象本身是无状态的。要跟踪某个值(或当前值),您将需要使用Subject
或BehaviorSubject
。
在您的currentPlayerService
中,创建一个名为BehaviorSubject
的playerBSubject
:
export class CurrentPlayerService{
public playerBSubject: BehaviorSubject<any>;//can be type of Player if you have such type
constructor(){
this.playerBSubject = new BehaviorSubject({})//any value that you want to initialize
}
getPlayer(){
//do your logic here, whatever that is.
//I am using an Observable.of to mimic a http request
Observable.of({})
.subscribe((player)=>{
this.playerBSubject.next(player)//this will update the subject with the latest value
});
return this.playerBSubject.asObservable();
}
}
请注意,
.next()
方法将更新您的主题的值,您可以使用.asObservable()
将其作为可观察的返回。现在,在组件 Controller 中,您可以检查
BehaviourSubject
是否存在(或具有所需的值),并且仅在需要时调用playerService.getPlayer()
。this.route.params.subscribe(params => {
//check if BehaviorSubject exist or not
if (this.currentPlayerService.playerBSubject.getValue() === {}) {
this.playerService.getPlayer(params.id)
.subscribe((player) => {
this.currentPlayer = player;
this.currentPlayerService.setPlayer(player);
});
}
});
意见建议:
我不确定为什么需要两个服务,即
currentPlayerService
和playerService
。如果您的currentPlayerService
仅用于跟踪播放器的“当前”值,则根本不需要它,如果您使用BehaviorSubject来跟踪当前播放器。所有这些都可以归结为一项服务。export class PlayerService {
public playerBSubject: BehaviorSubject<any>;
constructor() {
this.playerBSubject = new BehaviorSubject({})
}
getPlayer(id) {
Observable.of({id}) // implement your own logic
.subscribe((player) => {
this.playerBSubject.next(player)
});
return this.playerBSubject.asObservable();
}
setPlayer(id) {
return Observable.of({id})//implement your own logic
.subscribe(newPlayer => this.playerBSubject.next(newPlayer))
}
}
在 Controller 中,如果要获取当前值,可以执行以下操作:
this.currentPlayer = this.playerService.playerBSubject.getValue();
在
asObservable
的帮助下,您可以执行以下操作:this.playerService
.asObservable()
.subscribe(player => {
if (player === {}) {
this.route.params.subscribe(params => {
this.playerService.getPlayer(params.id); //voila, your player is updated
})
}
//remember to update the value
this.currentPlayer = player
})