【问题标题】:Angular Observable subscription fallback?Angular Observable 订阅后备?
【发布时间】:2017-11-30 00:33:26
【问题描述】:

我正在使用 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 的方法,因此我们将不胜感激。

谢谢!

【问题讨论】:

  • 你能展示你的播放器服务吗?
  • 我建议你注册到一个单一的位置,你的 currentPlayerService,如果它检测到它可以直接从参数中检索用户,那么它会这样做,如果不是,它将使用它的当前方法.您的应用程序的基本单点真理应该是“getPlayer”
  • (喜欢你的展示图片)。 “负载值”是什么意思。您是否正在缓存 http currentUser 响应?
  • 为什么不总是使用playerService.getPlayer 来获取当前播放器,而总是在初始化时使用currentPlayerService.setPlayer(player) 来设置播放器从路由?然后在setPlayer 中,如果你愿意,你可以处理如果值已经/没有改变的情况

标签: javascript angular typescript rxjs


【解决方案1】:

Observables 本身是无状态的。要跟踪某个值(或当前值),您需要使用SubjectBehaviorSubject

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

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() 将其作为可观察对象返回。

现在,在您的组件控制器中,您可以检查您的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))
    }
}

如果你想在你的控制器中获取当前值,你可以这样做:

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

【讨论】:

    猜你喜欢
    • 2018-07-13
    • 2020-06-19
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    • 2019-08-16
    • 2018-12-12
    相关资源
    最近更新 更多