2017-11-25 127 views
-1

我有,我定义的全局观察到,像这样一个服务:角度可观察到被称为多次

@Injectable() 
    export class XYZService { 
    country: Observable<any>; 
    isBrowser: boolean; 

    constructor(private http: Http, 
       private httpClient: HttpClient, 
       private router: Router, 
       @Inject(PLATFORM_ID) private platformId: any) { 
     this.isBrowser = isPlatformBrowser(platformId); 
     if(this.isBrowser && !this.country) { 
     this.country = this.http.get('https://ipinfo.io') 
     .map(res => res.json()) 
     .catch(() => { 
      return Observable.of({'country': 'SG'}); 
     }); 
     }; 
    } 

    getLocation(): Observable<any> { 
     return this.country; 
    } 

现在,在我的几个组件我打电话构造或ngOnInit像这样的getLocation功能:

this.XYZService.getLocation() 
    .subscribe(res => { 
    this.country = res['country']; 
}); 

我的期望是,对ipinfo.io的请求只能进行一次。但是,这并没有发生。从网络日志中我可以看到对ipinfo的请求正在多次进行。看起来是一些时间问题。如果我在构造函数中添加一个调试器或console.log语句,它只会被调用一次。然而,不止一个请求被发送。

+0

我想知道为什么你一起使用Http和HttpClient?他们都有不同的实现,我建议你只使用HttpClient然后尝试。 –

+2

这不是一个计时问题。这就是观测值的工作原理。要缓存结果,你必须使用'publishReplay()。refCount()':http://plnkr.co/edit/rvucIT6DF6nZmqNP7zzT?p=preview。阅读http://reactivex.io/rxjs/manual/overview.html#multicasted-observables –

回答

1

您可以使用rxjs share运算符。这将确保后续的用户将共享相同的可观测序列(直到观察家收益为0的个数)

this.country = this.http.get('https://ipinfo.io') 
    .map(res => res.json()) 
    .catch(() => { 
     return Observable.of({'country': 'SG'}); 
    }) 
    .share(); 

您也可以使用shareReplay操作。不同之处在于将来可以为任何订户存储可观察的结果。例如,假设您在应用程序加载时订阅了observable,在您订阅10分钟以上时订阅了shareReplay,则observable将返回相同的结果并且不会发出另一个http请求。而share,在初始http请求完成后,观察者的数量返回到0。未来订阅将触发另一个http请求