👉今回の構成
Angular4を使ってます。
👉今回の経緯
同じページで複数の子コンポーネントから同じリクエストを投げていたのを1回のリクエストで済ませたかった。
👉やったこと
HttpClientをもったサービスを作り、Getリクエストに対してBehaviorSubjectをObservableにして返すメソッドをはやした。
👉 やってないこと
GETパラメータ対応とかやってない…
BehaviorSubjectの初期値を決めなきゃならなかったので配列限定にした…
とまあ実際にいろいろアプリに組み込む上であとで掲載するコードよりはもう少しファットになっているのですが、BehaviorSubject便利!の一つとしてシンプルに伝わればいいかなと思い省いています。
Subjectとは?
nextメソッドで流れてきた値をSubscriberに流す、SubscriberでありObservableなやつ
const subject = new Subject<number>(); subject.subscribe(number => console.log(number)); subject.next(1); //出力: 1
BehaiviorSubjectとは?
Subjectに前回の値を保持する機能をもったもの。
.subscribeされたときに前回保持した値を最初に流す。
const behaiviorSubject = new BehaiviorSubject<number>(1); //Subjectと違い初期値をいれる必要あり subject.subscribe(number => console.log(number)); //初期値が流れてくる //出力: 1 subject.next(2); //出力: 2 subject.subscribe(number => console.log(number)); //出力: 2
HTTPリクエストに使ってレスポンスを保持したもの
リクエストパスをキーに リクエストパス: BehaiviorSubject
のMapを持っている。
getメソッド呼び出し時に
MapになければHTTPリクエスト、
MapにあればBehaiviorSubjectをObservableにして返す。
といったことをしております。
export class CachedApiService { private requestMap: Map<string, BehaviorSubject<any[]>> = new Map(); constructor(private http: HttpClient) {} get<T>(path: string) { if (!this.requestMap.get(path)) { this.requestMap.set(path, new BehaviorSubject<T[]>([])); this.http.get<T[]>(path, { params: this.params }).subscribe( response => { this.requestMap.get(path).next(response); }, error => this.requestMap.get(path).error(error) ); } return this.requestMap.get(path).asObservable() as Observable<T[]>; } }
Angularでよかったこと
キャッシュ系っていつ更新するのか、とかどこに保持しておくのとか考える&管理するのが面倒なイメージだったのですが、AngularのServiceとして作ることで表示する一番親ページのproviderとして呼び出せば同じページ内だけ重複したリクエストが飛ばない仕様にでき楽でした。
以下呼び出すとき
@Component({ selector: 'app-parent', templateUrl: './parent.component.html', styleUrls: ['./parent.component.scss'], providers: [ CachedApiService ] // ← ここ }) export class ParentComponent implements OnInit { ...
簡単ですが以上です!!