|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Czy wiesz, że za pomocą operatora shareReplay możesz cache'ować dane z observable? |
| 4 | +description: "" |
| 5 | +date: 2025-11-17T08:00:00+01:00 |
| 6 | +published: true |
| 7 | +didyouknow: false |
| 8 | +lang: pl |
| 9 | +author: ptatarski |
| 10 | +image: /assets/img/posts/2025-11-17-czy-wiesz-ze-za-pomoca-operatora-sharereplay-mozesz-cache-owac-dane-z-observable/thumbnail.webp |
| 11 | +tags: |
| 12 | +- rxjs |
| 13 | +- observable |
| 14 | +--- |
| 15 | + |
| 16 | +Często zdarza się, że nie chcemy za każdym razem ponownie wykonywać całej logiki z danego `Observable` — |
| 17 | +zamiast tego wolimy przechować jego wynik w pamięci. W Angularze (i ogólnie w RxJS) możemy to zrobić za pomocą operatora `shareReplay`. |
| 18 | + |
| 19 | +## Czym jest shareReplay? |
| 20 | +Operator `shareReplay` (tak jak operator `share`) pozwala na konwersję z *cold* do *hot* observable, |
| 21 | +tak aby każda subskrypcja korzystała z tej samej emisji observable. Dodatkowo dane są zapisywane w wewnętrznym **ReplaySubject** |
| 22 | +(w przeciwieństwie do operatora share), przez co każda nowa subskrypcja dostaje ostatnią wyemitowaną wartość (lub wartości jeżeli `bufferSize > 1`). |
| 23 | + |
| 24 | +## Przykład użycia |
| 25 | +W przykładzie poniżej generujemy losową liczbę. Normalnie przy każdej subskrypcji otrzymalibyśmy nowy wynik, |
| 26 | +ale dzięki `shareReplay` obie subskrypcje dostają dokładnie tę wartość. |
| 27 | +```typescript |
| 28 | +const source$: Observable<number> = of(Math.round(Math.random() * 1000)) |
| 29 | + .pipe(shareReplay()); |
| 30 | +source$.subscribe((x: number) => console.log('s1: ', x)); |
| 31 | +source$.subscribe((x: number) => console.log('s2: ', x)); |
| 32 | +``` |
| 33 | +W efekcie w konsoli pojawi się ta sama liczba w obu subskrypcjach, np.: |
| 34 | +```shell |
| 35 | +s1: 742 |
| 36 | +s2: 742 |
| 37 | +``` |
| 38 | +## Opcje konfiguracji |
| 39 | +Operator `shareReplay` posiada także dodatkowe opcje do skonfigurowania: |
| 40 | +- `bufferSize` - określa wielkość wewnętrznego ReplaySubject (domyślnie przechowuje ostatnią wartość), |
| 41 | +- `refCount` - określa, czy w momencie, gdy liczba subskrybentów wyniesie 0 shareReplay ma odsubskrybować się od źródłowego observable, co spowoduje wyczyszczenie cache (domyślnie false), |
| 42 | +- `windowTime` - ogranicza czas przechowywania wartości (czego domyślnie nie robi). |
| 43 | + |
| 44 | + |
| 45 | +### Przykład z dodatkowymi opcjami konfiguracji |
| 46 | +Załóżmy, że chcemy cache’ować więcej niż jedną wartość i dodatkowo kontrolować czas ich przechowywania. |
| 47 | +```typescript |
| 48 | +shareReplay({ bufferSize: 3, refCount: true, windowTime: 500 }) |
| 49 | +``` |
| 50 | +W rezultacie: |
| 51 | +- zostaną umieszczone w buforze 3 ostatnie wartości, |
| 52 | +- każda z osobna będzie miała czas życia ustawiony na pół sekundy, |
| 53 | +- w momencie, gdy nie będzie żadnej aktywnej subskrypcji, bufor zostanie wyczyszczony. |
| 54 | + |
| 55 | +### Przydatne linki |
| 56 | +[StackBlitz - Przykład interaktywny](https://stackblitz.com/edit/rxjs-ewsunmdz?file=index.ts) |
| 57 | + |
| 58 | +[Rxjs - Oficjalna dokumentacja](https://rxjs.dev/api/index/function/shareReplay) |
| 59 | + |
| 60 | +[Github - Kod źródłowy](https://github.com/ReactiveX/rxjs/blob/b25db9f369b07f26cf2fc11714ec1990b78a4536/src/internal/operators/shareReplay.ts#L26-L37) |
0 commit comments