Problema
Me suscribo a un httpClient.get observable dos veces. Sin embargo, esto significa que mi llamada se ejecuta dos veces. ¿Por qué es esto?
Prueba
Por cada suscripción () que hago, obtengo otra línea en la página de inicio de sesión.
Código (onSubmit () desde el botón de la página de inicio de sesión)
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'); } );
Consola
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
antecedentes irrelevantes
Tengo un objeto LogonService que maneja toda mi funcionalidad de inicio de sesión. Contiene una variable booleana que muestra si estoy conectado o no. Cada vez que llamo a la función de inicio de sesión, se suscribe al observable de httpClient.get, para establecer la variable de inicio de sesión en verdadero o falso. Pero la función de inicio de sesión también devuelve el observable, al que se suscribe. Me tomó un tiempo vincular la solicitud doble a la suscripción doble. Si hay una mejor manera de rastrear el inicio de sesión que a través de una variable, ¡házmelo saber! Estoy tratando de aprender angular :)
Puede usar el operador share
en su resultado de HttpClient.get
, así:
var observable = this.httpClient.get('api/version/secured', { headers: httpHeaders }) .pipe(share());
Deberá agregar la siguiente importación en la parte superior de su secuencia de comandos:
import { share } from 'rxjs/operators';
El operador de share
hace un observable hot
, es decir compartido entre suscriptores. Pero hay mucho más, sugeriría este artículo para profundizar más (por supuesto, también puede buscar en Google hot vs cold observables
para encontrar más).
Tu observable es frío:
Un observable es frío si el productor de sus notificaciones se crea cada vez que un observador se suscribe al observable. Por ejemplo, un temporizador observable está frío; cada vez que se realiza una suscripción, se crea un nuevo temporizador.
Necesita multicast
su Observable, o en otras palabras, para calentarlo:
Un observable está de moda si el productor de sus notificaciones no se crea cada vez que un observador se suscribe al observable. Por ejemplo, un observable creado usando fromEvent está caliente; el elemento que produce los eventos existe en el DOM; no se crea cuando el observador está suscrito.
Para esto, puede usar el operador compartido , pero aún no puede garantizarle una sola llamada http. Share multicast
su observable, haciéndolo compartido entre los suscriptores, pero una vez que se complete la llamada http, realizará una nueva llamada http para los nuevos suscriptores.
Si desea un comportamiento de almacenamiento en caché (realizar la llamada una vez y luego proporcionar el valor a cada suscriptor cada vez que se suscribe), debe usar publishReplay().refCount()
.
Además de las respuestas anteriores, puede asignar a observable su servicio http
y luego suscribirse a la obtención de datos. Por ejemplo:
export class App implements OnInit { lessons$: Observable<Lessons[]>; constructor(private lessonsService: lessonsService) { } ngOnInit() { this.lessons$ = this.lessonsService.loadLessons().publishLast().refCount(); this.lessons$.subscribe( () => console.log('lessons loaded'), console.error ); } }