Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 我该如何重构这个角度2的可观测值,以避免在路线改变时重复_Angular_Rxjs_Angular2 Observables - Fatal编程技术网

Angular 我该如何重构这个角度2的可观测值,以避免在路线改变时重复

Angular 我该如何重构这个角度2的可观测值,以避免在路线改变时重复,angular,rxjs,angular2-observables,Angular,Rxjs,Angular2 Observables,我有这个工作的罚款为我在目前,如果页面保持静态如下 使用服务获取要重复的计时器上http调用的结果 this.lts.getEventDetails(link,currentTime) .subscribe(res=>{ this.rs.setCurrentRace(activeRound['uid'],res.S); }) 在我的服务中调用此函数 getEventDetails(liveTimingLink:string,time:number){ let lin

我有这个工作的罚款为我在目前,如果页面保持静态如下

使用服务获取要重复的计时器上http调用的结果

this.lts.getEventDetails(link,currentTime)
  .subscribe(res=>{
    this.rs.setCurrentRace(activeRound['uid'],res.S);
  })
在我的服务中调用此函数

getEventDetails(liveTimingLink:string,time:number){

  let link  = `${liveTimingLink}?R=${time}`
  let timer = 5000;

  Observable
    .interval(timer)
    .flatMap(() => {
      return this.http.get(link)
        .map(res=>{return res.json()})
    })
}
问题是每次我改变路线回来时,它都会复制可观察到的计时器

我不确定我应该如何处理这个问题,我想我应该在服务中将observable设置为一个变量,然后返回它,但我不知道我该怎么做

或者我应该像现在这样做,只是随着路线的改变而取消订阅?我也不知道该怎么做


任何建议和想法都是非常受欢迎的。谢谢大家

您在方法调用之外创建可观察对象的想法很好

但是。。。每个
.subscribe()
可观察对象接收调用可观察对象的新执行。

这意味着仅仅有一个可观测的实例是不够的。您还需要在所有订阅者之间共享执行

起初,我认为您可以使用操作符,但只要它至少有一个订户,它将只共享可观察的。在您的情况下,它不起作用,因为当用户离开页面时,可观察对象将丢失其唯一订户。下次用户访问页面时,可观察对象需要从头开始重新执行(换句话说,间隔重置)。我怀疑这不是你想要的

我找到了一个解决方案,它使用操作符来共享可观察对象,并
.connect()
使其在第一次检索时开始发出值。无论您是否订阅,间隔都会持续运行

看看这个,看看它的行动。订阅/取消订阅按钮复制用户导航到/离开页面时发生的情况。打开浏览器控制台以查看订阅者接收到的值

服务代码:

@Injectable()
类MyService{
//创建一次间隔并在所有订阅者之间共享。
source=Observable.interval(1000).publish();
intervalStarted=false;
getEventDetails(参数){
//第一次检索可观察对象时,
//连接到它(=使它开始发射值)。
如果(!this.intervalStarted){
this.source.connect();
this.intervalStarted=true;
}
//在这里,继续使用诸如mergeMap()之类的运算符变换原始可观察对象。
返回这个.source.map(val=>`${val}-${param}`);
}
}
关于
getEventDetails()
方法版本的一些小说明:

  • 您可以将
    {}
    放在箭头函数的主体周围。这样您将得到一个隐式的
    返回
    ,您的代码将更加紧凑。不过,为了便于阅读,您可能需要保留您的版本
  • 如果您使用的是Angular2+,那么您使用的是RxJS 5,“官方”操作符是
    mergeMap()
    flatMap()
    来自RxJS 4,只是
    mergeMap()
    的别名
  • 由于方法中的局部变量不变,因此可以使用
    const
    vs
    let
    声明它们
  • 为什么在可观察的
    之前没有
    返回
    。间隔
以下是重写的方法:

getEventDetails(liveTimingLink:string,time:number){
const link=`${liveTimingLink}?R=${time}`;
常数定时器=5000;
可观测回波
.时间间隔(计时器)
.flatMap(()=>this.http.get(link.map)(res=>res.json())
}

我回到这里,感谢您对这个问题的想法和建议,我一直很感谢经验丰富的程序员的反馈

最后,我重新编写了代码,只需取消订阅可观察的路线更改。看起来比较简单,而且照顾到了我的需要

服务:

getEventDetails(liveTimingLink:string,time:number){

  const link  = `${liveTimingLink}?R=${time}`
  const timer = 5000;

  return Observable
    .interval(timer)
    .flatMap(() => {
      return this.http.get(link)
        .map(res=>{return res.json()})
    })
  }
组成部分:

saveLiveRaceString(serie:FirebaseObjectObservable<any>,activeRound){

  /**
    Only map & subscribe if current event has begun.
  **/

  const currentUnix = moment().unix();

  if(currentUnix > activeRound['mainEventUnix'] ){

    this.eventSubscription = this.lts.getEventDetails(serie['liveTimingLink'],currentUnix)
      .subscribe(res=>{
        this.rs.setCurrentRace(activeRound['uid'],res.S);
      })
  }

}

ngOnDestroy() { 

  /**
    Unsubscribe from the event observable
  **/

  this.eventSubscription?this.eventSubscription.unsubscribe():null
}
saveLiveRaceString(系列:FirebaseObjectObservable,activeRound){
/**
仅在当前事件已开始时映射和订阅。
**/
const currentUnix=moment().unix();
如果(currentUnix>activeRound['mainEventUnix']){
this.eventSubscription=this.lts.getEventDetails(serie['liveTimingLink',currentUnix)
.订阅(res=>{
这个.rs.setCurrentRace(activeRound['uid'],res.S);
})
}
}
ngOnDestroy(){
/**
取消订阅可观察到的事件
**/
this.eventSubscription?this.eventSubscription.unsubscripte():null
}