0

In my angular application I have a service that loads data from a server.

load.service.ts:

load = new Observable(observer => {
  console.log('load function called');
  // async stuff that takes time

  observer.complete();
});

I also have a bunch of components that all need to wait until the load observable completes. I do this like this:

this.loadService.load.subscribe(
  change => {},
  error => {},
  () => {
    // do stuff with data
  }
);

However, if I have multiple components all subscribing, the load function gets called multiple times, sending lots of requests to the server (as seen by console.log('load function called');.

My Question

I know there are ways to get around this using Angular, but my question is this:

How do I have multiple subscriptions to one observable but only call the function once?

My question is not about caching data. It is about observables.

6
  • Possible duplicate of Angular 2 cache observable http result data Commented Jul 13, 2017 at 20:12
  • @jonrsharpe my question isn't about caching data. It's about observables Commented Jul 13, 2017 at 20:13
  • Please read my answer, I think you'll find it applies well to your situation too. You want multiple subscribers to one data source, which isn't unlike caching. Commented Jul 13, 2017 at 20:14
  • I did read your answer and it doesn't apply to my question. I used the load function as an example of how my question applies. I just want to know if it is possible to subscribe to a function without calling it multiple times Commented Jul 13, 2017 at 20:23
  • Well, then: no, of course not. You can't "subscribe to a function". You can call a function, and subscribe to what it returns. With observables you can pass what it returns to other things, and they can subscribe too. But the point of the pattern I've shown is that you separate the trigger and the subscription, so you can fetch data once and easily subscribe from multiple places. You can also re-fetch from somewhere, and all subscribers get the new data when it arrives. Commented Jul 13, 2017 at 20:25

3 Answers 3

2

Why not use BehaviourSubject to store what retuns from the loadService load method and subscribe to the BehaviourSubject. It should solve your problem. Angular 2 Brhaviour Subject vs Observable

Sign up to request clarification or add additional context in comments.

Comments

2

You have to understand how observables work. load is "cold", it means that new sequence will be started for each subscribe. You need to use share operator to make it "hot" and store somewhere reference to resulting observable:

 public load(){
      if(this.completed){
         this.shared = new Observable(...).share();
         this.shared.subscribe(()=> this.completed = true);
         this.completed = false;
      }
      return this.shared;
 }

Comments

0

RxJs have share() method. See RxJs documentation : https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/share.md

Here's another SO post related to this: How to call single ajax request by multiple components parallely in angular2 cli project

Hope that helps

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.