4

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

7
  • Could you show us that they trigger a request or are they just handling 1 response 3 times? Commented Nov 17, 2017 at 15:49
  • I can send you the screenshot of the Chrom-Network overview.... Commented Nov 17, 2017 at 16:08
  • I think your call and subscriptions are not supposed to be in the same function. You would normally have the subscriber in a component and the request being made from a service. Commented Nov 17, 2017 at 16:32
  • Yes, thats the usual use-case. But I just understand that anyway. And if it works properly after a return of the Promise/Observable it would confuse me even more :) Commented Nov 17, 2017 at 17:02
  • 1
    ...ALSO interesting fact: Using 'HttpClient' calls and listening only '.toPromise()' does NOT trigger any Angular Interceptors. Commented Nov 17, 2017 at 17:37

1 Answer 1

3

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.

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

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.