1

In my Angular application, I have the subscription in every single component for watching if the user's Company change. On app init I download user's Company, so subscription fires once in every component I'm subscribing for changes in the state of the company (it's necessary because I am using this Company data in most of them). One of my components have a subscription to Company, and it downloads data once on init. When I change the view, a subscription is no more fired, so I need to download data. Code looks like

    this.subscription = this
    .companyService
    .CompanyState
    .subscribe((company: Company) => {
        this.getSomeData()
    })
    this.getSomeData()

I've tried adding some flag like needDownload with default value true, and set it to false if subscription fires this.getSomeData(), but it's async and doesn't work very well. If I remove the subscription from this component, I will stop watching changes on Company state. If I remove this.getSomeData() from the end of this code, I will not get data if the component is initiated without default call on subscription. The problem is I am downloading data twice, and I feel like it's possible to do it once.

Hardik Shah
  • 4,042
  • 2
  • 20
  • 41
ifeelmyself
  • 99
  • 1
  • 11
  • Show us how you define `CompanyState` in the service. – ConnorsFan Jul 11 '18 at 13:41
  • First, I define companySubject - `private companySubject = new Subject()`, and then I make it observable. `public CompanyState = this.companySubject.asObservable()` and then in `getUserCompany` function, on response I fire `this.companySubject.next(res.json()))` – ifeelmyself Jul 11 '18 at 13:45
  • I think you should create a Shared Service that gets the data and have a single source of data, then on your components inject that shared service that will access the state of your data that can be updated on any part of the module you use the Shared Service – CREM Jul 11 '18 at 13:48

1 Answers1

2

In your service, you can define companySubject as a ReplaySubject instead of a Subject. The buffer size can be set to 1, so that it "replays" only the last emitted value.

private companySubject = new ReplaySubject<Company>(1);

A new view will be notified as soon as it subscribes to the observable, if CompanyState has already emitted a value. As a consequence, you can remove the direct call to getSomeData() in your component initialization code.

See this answer for details about the various Subject classes.

ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • But, if i get your idea, i will download data on every view change. If i am right, there is no other way to achieve this? – ifeelmyself Jul 11 '18 at 14:41
  • I am not sure that I understand your question. I thought that you wanted to make sure that `getSomeData` is called for the view if `CompanyState` has been triggered (and every time it will be triggered in the future). Please note that, with component reuse, `ngOnInit` is not necessarily called every time a component is displayed, if it has already been displayed before. – ConnorsFan Jul 11 '18 at 14:48
  • Okay, nevermind, i've solved out how does it really works, thank you one more time :) – ifeelmyself Jul 11 '18 at 14:54