Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 observable subscribing twice executes call twice

Problem
I subscribe to an httpClient.get observable twice. However, this means that my call gets executed twice. Why is this?

Proof
For every subscribe() I do, I get another line in the login page.

Code (onSubmit() from login page button)

var httpHeaders = new HttpHeaders()   .append("Authorization", 'Basic ' + btoa(this.username + ':' + this.password));  var observable = this.httpClient.get('api/version/secured', { headers: httpHeaders}); observable.subscribe(   () => {     console.log('First request completed');   },   (error: HttpErrorResponse) => {     console.log('First request error');   } ); observable.subscribe(   () => {     console.log('Second request completed');   },   (error: HttpErrorResponse) => {     console.log('Second request error');   } ); 

Console

zone.js:2935 GET http://localhost:4200/api/version/secured 401 (Unauthorized) login.component.ts:54 First request error zone.js:2935 GET http://localhost:4200/api/version/secured 401 (Unauthorized) login.component.ts:62 First request error 

Irrelevant background
I have a LogonService object which handles al my login functionality. It contains a boolean variable that shows whether I am logged in or not. Whenever I call the login function, it subscribes to the observable of the httpClient.get, to set the login variable to true or false. But the login function also returns the observable, which gets subscribed to. Took me some time to link the double request to the double subscription. If there is a better way of tracking the login than through a variable, let me know! I am trying to learn angular :)

like image 875
Rico Avatar asked Mar 10 '18 11:03

Rico


People also ask

What happens when you subscribe to an Observable?

An Observable instance begins publishing values only when someone subscribes to it. You subscribe by calling the subscribe() method of the instance, passing an observer object to receive the notifications. Returns an Observable instance that synchronously delivers the values provided as arguments.

Why subscribe is called twice?

The most common reason for this is that you have called subscribe() multiple times. Every time it is called it adds a new message listener, even if that same listener is already registered for that event; when a message is received, every registered listener will be called with it.

What happens if you don't subscribe to an Observable?

Remember, observables are lazy. If you don't subscribe nothing is going to happen. It's good to know that when you subscribe to an observer, each call of subscribe() will trigger it's own independent execution for that given observer. Subscribe calls are not shared among multiple subscribers to the same observable.

How do I subscribe to Observable only once?

If you want to call an Observable only one time, it means you are not going to wait for a stream from it. So using toPromise() instead of subscribe() would be enough in your case as toPromise() doesn't need unsubscription.


1 Answers

You may use the share operator on your result from HttpClient.get, like this:

var observable = this.httpClient.get('api/version/secured', { headers: httpHeaders })   .pipe(share()); 

You'll need to add the following import on top of your script:

import { share } from 'rxjs/operators'; 

The share operator makes an observable hot, i.e. shared between subscribers. But there's a lot more to it, I would suggest this article to dive deeper (you can of course also google up hot vs cold observables to find more).

like image 137
Jeto Avatar answered Sep 17 '22 21:09

Jeto