2017-11-25 4 views
-1

wird habe ich einen Dienst, bei dem ich mich wie so eine globale beobachtbar definiert:Angular beobachtbare mehrmals aufgerufen

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

nun in mehreren meiner Komponenten Ich bin die getLocation Funktion im Konstruktor oder ngOnInit Aufruf wie so :

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

Meine Erwartung ist, dass die Anfrage an ipinfo.io nur einmal gemacht werden würde. Aber das passiert nicht. Aus den Netzwerkprotokollen kann ich sehen, dass die Anfrage an ipinfo mehrfach gestellt wird. Sieht so aus, als wäre es ein Timing-Problem. Wenn ich im Konstruktor eine Debugger- oder console.log-Anweisung hinzufüge, wird diese nur einmal aufgerufen. Es werden jedoch mehr als eine Anfrage gesendet.

+0

Ich frage mich, warum Sie Http und HttpClient zusammen verwenden? Beide haben eine andere Implementierung, ich schlage vor, Sie verwenden nur den HttpClient und versuchen es dann. –

+2

Es ist kein Timing-Problem. So funktionieren Observables. Um das Ergebnis zwischenzuspeichern, müssten Sie 'publishReplay(). RefCount()': http://plnkr.co/edit/rvucIT6DF6nZmqNP7zzT?p=preview verwenden. Lesen Sie http://reactivex.io/rxjs/manual/overview.html#multicasted-observables –

Antwort

1

Sie können den Operator rxjs share verwenden. Dadurch wird sichergestellt, dass nachfolgende Teilnehmer die gleiche beobachtbare Folge (bis die Anzahl der Beobachter wieder auf 0) teilen

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

Sie auch die shareReplay Betreiber nutzen können. Der Unterschied besteht darin, dass das beobachtbare Ergebnis für zukünftige Abonnenten gespeichert wird. Angenommen, Sie abonnieren die Observable, wenn die App geladen wird, mit shareReplay, wenn Sie 10+ Minuten später abonnieren, wird die Observable das gleiche Ergebnis zurückgeben und keine weitere http-Anfrage stellen. Während mit share die Anzahl der Beobachter nach dem Ende der HTTP-Anforderung auf 0 zurückgeht. Die zukünftige subscribe wird eine weitere HTTP-Anfrage auslösen