4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-02-07

: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 {
...

簡単ですが以上です!!

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?