我正在使用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的方法,因此可以提供任何帮助。

谢谢!

最佳答案

可观察对象本身是无状态的。要跟踪某个值(或当前值),您将需要使用SubjectBehaviorSubject

在您的currentPlayerService中,创建一个名为BehaviorSubjectplayerBSubject:

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

意见建议:

我不确定为什么需要两个服务,即currentPlayerServiceplayerService。如果您的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
    })

09-10 12:20