0

In my service, I have a function which gets some data from the server. Several parts of my application call this function at init time. And what I'd like to do is that: if there is already one request being sent, the other wait for its response (they don't need to make their own request).

So my code is:

@Injectable()
export class UserService implements OnInit {
  ngOnInit(){
        this.getUserInformations();
  };

  public getUserInformations(forceRefresh?: boolean): Observable<Object>{

        if(this.userInformationsLastObservable == null) {
            console.log('Making a request'); // called only once at init
            this.userInformationsLastObservable = this.http.get(this.baseUrl + "informations")
            .map((result: Response) => {
                console.log('map is called'); // called 5 times at init
                let userInformations = result.json();
                /* So future calls will perform a new request */
                this.userInformationsLastObservable = null;
                return userInformations;
            });
        }

        return this.userInformationsLastObservable;
    };
}

And several components call it this way:

@Component({
  selector: 'app-leaderboard',
  templateUrl: 'leaderboard.component.html',
  styleUrls:  ['leaderboard.component.css'],
  providers: []

})
export class LeaderboardComponent implements OnInit
{
  ngOnInit(){
      this.userService.getUserInformations().subscribe((userInformations) => {
        this.userInformations = userInformations;
        /* this function does not make any call to the User service */
        this.refresh();
      }, () => {
        this.isLoading = false;
      });

    };
}

The problem is: from the Network panel of the console, I see that 5 requests are sent at init time. And 'map is called' is printed 5 times too, whereas 'Making a request' is only called once.

What am I doing wrong ?

Thanks for your help enter image description here enter image description here

Valentin Coudert
  • 1,759
  • 3
  • 19
  • 44

3 Answers3

1

Found out that the problem comes from my misunderstanding of how rxjs Observable work. I didn't know that each time you subscribe to one of them, it kinda re-executes it. Here, each time I subscribe to this.userInformationsLastObservable, it makes the http call again. I thought the call would only be made at creation time, and all the subscribers are then notified when a response is received.

So I guess I'll solve this problem by using a Subject.

Valentin Coudert
  • 1,759
  • 3
  • 19
  • 44
0

The request sent after receiving a response from another request should be registered in the subscription method of the service in the component.

In component:

constructor(private _service: Service) { }

ngOnInit() {
  this._service.getUserInformations().subscribe(
    res => {
      // call another service;
    }
}

Regardless of the length of the response array, the second request will be sent only once.

Emerceen
  • 2,735
  • 3
  • 17
  • 22
  • all the parts of my app call the same request, it's not "Send request 1, then send request 2". It's "send request 1, (... some time ...), send request 1". But if there is already one "request 1" pending, they should wait for it instead of doing another one. – Valentin Coudert Mar 21 '17 at 10:59
  • It does not matter if it is the same or different request. this.http.get(this.baseUrl + "informations") must return 5 elements array, and .map iterates 5 times, and 5 times call body. Check response from your api. – Emerceen Mar 21 '17 at 11:15
  • no the response is only one object, and I can see 5 calls in the network tab of the console. – Valentin Coudert Mar 21 '17 at 13:06
  • Please, paste the code snippet where you call the service method – Emerceen Mar 21 '17 at 13:14
  • Ok I've edited my post. There are calls in the service `onInit` and in components' `onInit` – Valentin Coudert Mar 21 '17 at 13:20
0
public getConfig(): ReplaySubject<HomeConfig> {

    if (this.replayConfigRequest) {
        return this.replayConfigRequest;
    }

    this.configRequest = this.http.get<HomeConfig>(this.meta.configUrl);

    this.replayConfigRequest = new ReplaySubject<HomeConfig>(1);

    this.configRequest.subscribe(this.replayConfigRequest);

    return this.replayConfigRequest;
}
Saturn K
  • 2,705
  • 4
  • 26
  • 38