Http を使用して、ネットワーク呼び出しを実行し、http オブザーバブルを返すメソッドを呼び出します。
getCustomer() {
return this.http.get('/someUrl').map(res => res.json());
}
この Observable に複数のサブスクライバーを追加すると、次のようになります。
let network$ = getCustomer();
let subscriber1 = network$.subscribe(...);
let subscriber2 = network$.subscribe(...);
私たちがやりたいのは、これによって複数のネットワーク要求が発生しないようにすることです。
これは珍しいシナリオのように思えるかもしれませんが、実際には非常に一般的です。たとえば、呼び出し元がエラー メッセージを表示するために observable をサブスクライブし、非同期パイプを使用してそれをテンプレートに渡す場合、すでに 2 つのサブスクライバーが存在します。
RxJs 5 でこれを行う正しい方法は何ですか?
つまり、これはうまく動作するようです:
getCustomer() {
return this.http.get('/someUrl').map(res => res.json()).share();
}
しかし、これは RxJs 5 でこれを行う慣用的な方法でしょうか、それとも代わりに何か他の方法を行うべきでしょうか?
注: Angular 5 の新機能によりHttpClient
、.map(res => res.json())
JSON 結果がデフォルトで想定されるようになったため、すべての例の 部分は役に立たなくなりました。
ベストアンサー1
編集: 2021 年現在、適切な方法は、shareReplay
RxJs によってネイティブに提案された演算子を使用することです。詳細については、以下の回答を参照してください。
データをキャッシュし、キャッシュが利用可能な場合はこれを返し、そうでない場合は HTTP リクエストを実行します。
import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of'; //proper way to import the 'of' operator
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import {Data} from './data';
@Injectable()
export class DataService {
private url: string = 'https://cors-test.appspot.com/test';
private data: Data;
private observable: Observable<any>;
constructor(private http: Http) {}
getData() {
if(this.data) {
// if `data` is available just return it as `Observable`
return Observable.of(this.data);
} else if(this.observable) {
// if `this.observable` is set then the request is in progress
// return the `Observable` for the ongoing request
return this.observable;
} else {
// example header (not necessary)
let headers = new Headers();
headers.append('Content-Type', 'application/json');
// create the request, store the `Observable` for subsequent subscribers
this.observable = this.http.get(this.url, {
headers: headers
})
.map(response => {
// when the cached data is available we don't need the `Observable` reference anymore
this.observable = null;
if(response.status == 400) {
return "FAILURE";
} else if(response.status == 200) {
this.data = new Data(response.json());
return this.data;
}
// make it shared so more than one subscriber can get the result
})
.share();
return this.observable;
}
}
}
この記事https://blog.thoughtram.io/angular/2018/03/05/advanced-caching-with-rxjs.htmlキャッシュする方法についての優れた説明ですshareReplay
。