How to share your RxJS observables for improved performance

Поделиться
HTML-код
  • Опубликовано: 11 июл 2024
  • My modern Angular course: angularstart.com/
    In this tutorial, we investigate how to cache and share an observable stream so that we don't need to continually call the set up code for the source observable for each new subscription (e.g. we don't need to make multiple HTTP requests, or set up web sockets, or other potentially expensive operations).
    Get weekly content and tips exclusive to my newsletter: mobirony.ck.page/4a331b9076
    0:00 Introduction
    0:56 A "cold" observable
    2:38 Caching the observable
    3:40 Making it "hot" with share
    5:22 shareReplay
    7:48 refCount
    Caching and Sharing Firestore Data with RxJS and ShareReplay: eliteionic.com/tutorials/cach...
    #angular #rxjs #observables
    - More tutorials: eliteionic.com
    - Follow me on Twitter: / joshuamorony

Комментарии • 34

  • @Kyumia
    @Kyumia Год назад +47

    For the people watching this almost a year later, Ben Lesh (RxJS dev) recommends using share({connector: new ReplaySubject(1)}) instead of shareReplay({bufferSize: 1, refCount: true}). It's the equivalent; the refCount is already set to true in the share() operator. The RxJS devs said they would probably deprecate shareReplay(1) in the future like the other multicasting operators such as: multicast, publish, publishReplay, publishLast, and refCount (already deprecated in RxJS 7). shareReplay still only exists due to its popularity and is now a wrapper around the highly configurable share operator. Source: Reactive Patterns with RxJS for Angular (e-Book)

    • @deluxe9490
      @deluxe9490 Год назад +1

      Thanks for advic

    • @daguttt
      @daguttt 11 месяцев назад

      Just by using the share() operator like you said RxJS devs recommends it to do so does not work. I mean doing `share({ connector () => new ReplaySubject(1)})` does not behave the same as `shareReplay(1)` because if the source observable behind the `share()` approach completes, the share operator connected to the ReplaySubject is going to mirror that completion when `shareReplay(1)` is not.
      Can you reference the concrete example of the e-Book?

    • @daguttt
      @daguttt 11 месяцев назад

      Code reference: ...
      ```ts
      import { of, tap, share, shareReplay, ReplaySubject } from 'rxjs';
      const source = of(1, 2, 3).pipe(
      tap((val) => console.log(`Source emitted ${val}`)),
      // share() // Replace with shareReplay(1) to see the difference
      // shareReplay(1),
      share({ connector: () => new ReplaySubject(1) })
      );
      source.subscribe((val) => console.log(`Subscriber 1 received ${val}`));
      setTimeout(() => {
      source.subscribe((val) => console.log(`Subscriber 2 received ${val}`));
      }, 5000);
      ```

  • @buildmore9829
    @buildmore9829 2 года назад +2

    Finally found someone who not just knows it deep but is able to explain it ! Thanks

  • @greatsuccess4734
    @greatsuccess4734 2 года назад +10

    The way you explain the details is just awesome. Keep these rxjs videos coming. Thanks

  • @salehabuhussein8175
    @salehabuhussein8175 2 месяца назад

    You are the GOAT of angular and reactive programming

  • @olmanmora21
    @olmanmora21 Год назад

    This channel is a must-follow for any Angular Dev

  • @NickCarboneDrum
    @NickCarboneDrum Год назад

    Your communication skills are next level. Kudos and thank you! 🎉🎉🎉

  • @sergioccarneiro
    @sergioccarneiro 2 года назад +1

    The refCount was the icing on the cake 👌

  • @ksivasuriyaprakash9976
    @ksivasuriyaprakash9976 2 года назад

    Thanks for sharing!

  • @gosnooky
    @gosnooky 10 месяцев назад

    This a great channel. I don't use Angular - never have, never will, but I do use NestJS quite often and it's "Angular-inspired" and uses RxJS under the hood. Sometimes I need to tap into their use of observables and I never understand RxJS very well, but these videos help.

  • @CrusaderMen
    @CrusaderMen 2 года назад

    Thank you!

  • @BraveTravelerK
    @BraveTravelerK 2 года назад

    Really nice content and well explained, but I just got a few notes you might want to take into your next video:
    - avoid implicit any as return-type for methods (eg. getclients() )
    - maybe show the approach on how to build a ReplaySubject itself instead of an Observerable object
    - import stricter linter rules
    These are all optional but IMHO make the code alot more understandable/readable.

    • @JoshuaMorony
      @JoshuaMorony  2 года назад +4

      Thanks for the suggestions! Just a note on implicit any - getClients etc. doesn't have an implicit any type here, the return type is inferred as Observable. Although I can get behind supplying explicit types for return types anyway, this is something I flip flop on a bit but in general I think it's good for readability.

  • @lithixz
    @lithixz 2 года назад

    Thanks for providing that detailed insight.
    Could you create a video on how to implement the updateClient methods etc. for that performant version as I am having my struggles on adapting to the other methods.

  • @Exiltruman
    @Exiltruman Год назад

    Great video, Joshua!
    One thing though, in "watchClient" you could have used "filter" operator instead of "map" with "find".

    • @JoshuaMorony
      @JoshuaMorony  Год назад

      Thanks! map/find is required in this case because the stream emissions are arrays containing all of the clients - a filter would block/allow the entire array from being emitted, in this case I want to pull just one item out of that array.

  • @sick911
    @sick911 2 года назад

    Hi Joshua great video, a question about the check to see if you have clients, in a case where the request returns a subset of clients and need the next subset how would you do that?

  • @Alex-bc3xe
    @Alex-bc3xe Год назад +1

    If you want the latest data from the database you need to make again a http get request or can you somehow listen continually to the database

  • @tanishqmanuja
    @tanishqmanuja 2 года назад

    Thanks for amazing content as usual . Can u also make a video explaining difference between behavioural subject vs replay subject vs share replay and the whats the best scenario to use them. Couldn't understand that because rxjs docs are not that good IMHO

    • @JoshuaMorony
      @JoshuaMorony  2 года назад +5

      Subjects (BehaviorSubject and ReplaySubject) are in a different category to shareReplay which is an operator you can pipe onto an observable (which will effectively convert that observable into a ReplaySubject). A "Subject" is a special type of observable that allows you to share/multicast data to multiple subscribers (i.e. a "hot" observable).
      A BehaviorSubject is a Subject that always has an initial value and will always emit that value, or whatever the latest data emission was if its "next" method has been triggered, when something subscribes to it. This is often in an Angular service where you want to load some data or update some data and expose it throughout your app using an observable. Whatever subscribes to it will always get the latest value when the subscription happens, and if there have been no data emissions yet it will get that initial value that has to be supplied to it when you create it.
      A ReplaySubject is a Subject that will repeat X amount of the previous data emissions when something subscribes to it. If the ReplaySubject has already emitted three values (1, 2, 3) and then something subscribes to it, that subscriber will receive the old data emissions when it subscribes (1, 2, 3).

    • @tanishqmanuja
      @tanishqmanuja 2 года назад

      Thanks @@JoshuaMorony , Now it is starting to make sense for me . So i think behavioural subject would be good for general use cases.
      PS: It genuinely feels great when a youtuber make time for a detailed reply. Appreciate it !

    • @JoshuaMorony
      @JoshuaMorony  2 года назад +1

      @@tanishqmanuja Yes definitely, a super common use case is to use a BehaviorSubject to manage data in a service (think "posts", "clients", "items" etc.). Then that service would provide a method like "getPosts()" which would return the BehaviorSubject as an observable for use outside of the service. If you set the return type on the get method to be an Observable, it prevents other parts of the app from calling the BehaviorSubjects "next" method (instead things outside of the service just get access to the stream of data)

  • @PabloEmanuelCabrera
    @PabloEmanuelCabrera Год назад +2

    What happens if instead of using firestore you get the data by doing a http request? How can I update my clients$ value with the new data? I mean, is there way to re-execute the http request after we know the database has been updated?

    • @JoshuaMorony
      @JoshuaMorony  Год назад +1

      The HTTP request just completes and that is it once it has fetched the data (even though it is delivered via an observable). If you aren't using something like Firestore that streams updates by default, you might want to look into using web sockets for live updates.

    • @seanszarkowicz2910
      @seanszarkowicz2910 Год назад

      Hi Josh, great video as always. I have been struggling to find the solution to the same question. When using a backend SQL database you don't really want to be setting up websockets to just get data for an API. I like the solution to prevent multiple http calls from various components you have shown. But it would be nice if there was a way to make a new http call to refresh the data for all the component subscribers. I find this type of real world use case frustrating that this is not addressed by Angular in documentation examples. For example, users get a list of data, select an item from the list of data, update that item, now we want to get/refresh the list of data so that the info is correct when clicking on the item again. Pretty simple CRUD over http. Thanks again

  • @tuvok86
    @tuvok86 9 месяцев назад

    if i do exactly but with students instead of clients than i get an error TS2345: Argument of type 'MonoTypeOperatorFunction' is not assignable to parameter of type 'OperatorFunction'. I honestly never saw that before.

  • @MrLolhaha100
    @MrLolhaha100 2 года назад

    What if we have 2 different components? Say a list of clients, which upon clicking on a client name, it redirects to the client detail page. Will that still make use of the shareReplay observable and act like a centralised hub of data, akin to data management like ngrx? Thanks :)

    • @JoshuaMorony
      @JoshuaMorony  2 года назад

      Yes, if you're sharing a hot observable with your app using a singleton service then it doesn't matter what component subscribes to it - they will all share the same stream

  • @Asaloy
    @Asaloy 2 года назад

    You really should show it how it works with real data flowing and not just with showing code.

  • @florianfrank3618
    @florianfrank3618 Год назад

    Pleeease add returntypes to your methods 🥲