Angular HttpClient multiple calls

Viewed 3634

I found a disturbing fact in my Angular 5 App.

This little call in my service:

interface U{
  name:string;
}
...

constructor(private http : *Http*, private httpC:HttpClient) // Http is deprecated - its a compare test

...
ping() //Test Debug func
  {
    let o:Observable<U> = this.httpC.get<U>(this.url + "user/1");

    o.subscribe(resp => {
      console.log("SUBSCRIBE1: Init:get:user:U: " + resp.name);
      return resp;
    },
    this.handleError);

    o.subscribe(resp => {
      console.log("SUBSCRIBE2: Init:get:user:U: " + resp.name);
      return resp;
    },
    this.handleError);

    o.toPromise().then(resp => {
      console.log("PROMISE: Init:get:user:U: " + resp.name);
      return resp;
    });
  }

Now on ping() call Angular/Browser is actually calling three times "url/user/1" Once for each listener (2 subscribes, 1 promise)

Is that used to be like this?

My understanding of an Observer is that I can add multiple "Listeners" which are waiting for an action. NOT trigger the action.

Whats wrong here? Do I have some broken setup after update or something?

Some clearence or an example how to do something like this right would be realy great! Thanks for any input.

EDIT: I extend the experiment with a further call with deprecated HTTP client which is doing the same. So it seems to be by design. Just dont understand how to catch multiple times WITHOUT calling multiple times.

 ping() //Test Debug func
  {
    let o:Observable<U> = this.httpC.get<U>(this.url + "user/1");

    o.subscribe(resp => {
      console.log("SUBSCRIBE1: Init:get:user:U: " + resp.name);
      console.log(resp);
      //this.currentUser = resp;
      return resp;
    },
    this.handleError);

    o.subscribe(resp => {
      console.log("SUBSCRIBE2: Init:get:user:U: " + resp.name);
      console.log(resp);
      //this.currentUser = resp;
      return resp;
    },
    this.handleError);

    o.toPromise().then(resp => {
      console.log("PROMISE1: Init:get:user:U: " + resp.name);
      console.log(resp);
      //this.currentUser = resp;
      return resp;
    });

    o.toPromise().then(resp => {
      console.log("PROMISE2: Init:get:user:U: " + resp.name);
      console.log(resp);
      //this.currentUser = resp;
      return resp;
    });


    let call:string = this.url + "user/1";
    return this.http.get(call)
        .toPromise()
        .then(resp => {
          console.log("OLD HTTP PROMISE 1 " + resp);

          return resp;
        })
        .catch(this.handleError)
        .then(resp => {
          console.log("OLD HTTP PROMISE 2 " + resp);

          return resp;
        });
  }

And this is what Chrome-Network shows after one ping call:

enter image description here

1 Answers

My understanding of an Observer is that I can add multiple "Listeners" which are waiting for an action. NOT trigger the action.

I think you are confusing subscribe() with a promise's then(). But Unlike with promises, where subsequent calls to then will return exactly the same result, calling subscribe() on a ''cold'' observable will not subscribe to the "same" result but will actually create a new "producer" with each subscribe() call and each "producer" will generate ("produce") a new distinct result. For a good explanation on hot and cold observables consider reading this great article by Ben Lesh.

Whats wrong here? Do I have some broken setup after update or something?

What I described above is what is also happening in your example with the HttpClient's get(): It creates a cold observable whose producer (i.e. the request) will be recreated (re-executed) on every call.

You can make the client's "cold" http-request observable "hot" though, i.e. sharing the objservable's source/sequence, using rxJS share() – or in your case preferably shareReplay, which replays values.

Related