コンパイラかく語りき

import { Fun } from 'programming'

【Angular/rxjs】shareReplay が unsubscribe 後も emit し続けメモリリークになりうる問題への対処法

概要

shareReplay を使うと複数の subscribe を一本化できて便利です。

stream$.pipe(shareReplay())

パフォーマンス改善の対処法としてよくやります。(share だと初期値の null が流れてきてしまうので、個人的には shareReplay の方が好みです。

参考: angular - RxJS: Share() an Observable & Emit Last Value to each new subscriber - Stack Overflow

問題

しかし、shareReplay が unsubscribe 後も emit し続けるという現象が発覚しました。(tap で console.log を仕込んでやると、ログが表示され続けることが確認できます)

自分のコードでは、Angular の template で async pipe を利用して subscribe していました。

なので、ページ遷移したら unsubscribe されて emit されないはずでは…?と思いました。

このままではメモリリークにつながる可能性があります。

対処法

対処法としては、config を設定してやります。

stream$.pipe(
  shareReplay({
    bufferSize: 1, // bufferSize の数値はお好みで
    refCount: true, // refCount は required で true を指定してやります
  })
)

refCount: true を指定することで、subscribe の数がカウントされます。この数が 0 になった時、stream が emit されなくなります。

無事に、ページ遷移後に emit されないことを確認できました。

参考