キャッシュするHTTPクライアントをBehaviorSubjectを使って実装してみた例

キャッシュするHTTPクライアントをBehaviorSubjectを使って実装してみた例:


:point_right: 今回の構成

Angular4を使ってます。


:point_right: 今回の経緯

同じページで複数の子コンポーネントから同じリクエストを投げていたのを1回のリクエストで済ませたかった。


:point_right: やったこと

HttpClientをもったサービスを作り、Getリクエストに対してBehaviorSubjectをObservableにして返すメソッドをはやした。


:point_right: やってないこと

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 { 
... 
簡単ですが以上です!!

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)