Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

191
Visualizações
Suscripción no deseada en el servicio observable

Siguiendo el patrón de servicio en caché, estoy usando un BehaviourSubject suscrito usando un Observable de solo lectura creado a partir de él en varios componentes

 // credential.service.ts private _credentialList$: BehaviorSubject<Credential[]> readonly credentialListObv$: Observable<Credential[]> ... this. credentialListObv$ = this.credentialList$.asObservable() ... getCredentialList(...): Observable<Credential[]> { return this.http.get<Credential[]>( `` ).pipe( tap(credList => { ... this._credentialList$.next(credList) }), ) }

Entonces, desde el componente, activé el método getCredentialList para emitir la lista obtenida por el sujeto _credentialList$ y, por lo tanto, todos los suscriptores de credentialListObv$ deberían obtener el valor.

El problema es que cuando creo mi componente obtendré una suscripción no deseada cuando invoco el método getCredentialList

 // credential-list.component.ts private _credentials$: Observable<Credential[]> constructor( private credentialService: CredentialService, ) { this._credentials$ = this.credentialService.credentialListObv$.pipe( tap(() => {console.log("sub")}), ... ) } ngAfterViewInit(): void { this.credentialService.getCredentialList(...).subscribe() } get credentials$() { return this._credentials$ } // credential-list.component.html <mat-expansion-panel *ngFor="let credential of credentials$ | async; let i=index"> ...

El resultado es que cuando accedo a la página "sub" se imprimirá dos veces. La primera suscripción ocurre desde la canalización async dentro de la plantilla del componente, pero ¿por qué hay otra si nunca invocaré subscribe en this._credentials$ del componente credential-list ?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Esto se debe a que también se está suscribiendo al método de servicio que devuelve el HTTP observable. Entonces ahora su componente tiene dos suscripciones activas a una llamada http.

Los métodos HTTP en Angular se completan después de emitir un valor, por lo que puede suscribirse de manera segura al observable dentro del método.

 getCredentialList(...): Observable<Credential[]> { this.http.get<Credential[]>( `` ).pipe( tap(credList => { ... this._credentialList$.next(credList) }), ).subscribe(); }

Luego, en su componente, deje su observable igual, pero no se suscriba al método.

 ngAfterViewInit(): void { this.credentialService.getCredentialList(...); }

Ahora, invocar el método de servicio activa la solicitud HTTP, y su observable privado _credentials$ aún obtiene los datos del BehaviorSubject.


Editar: dado que dijo que no desea suscribirse a nada dentro del servicio, puedo ofrecerle una solución que solo requiere una suscripción en la plantilla del componente.

 // credential.service.ts private credentialParams$ = new Subject<ApiParameters>(); public credentialListObv$: Observable<Credential[]>; ... this.credentialListObv$ = this.credentialParams$ .pipe( switchMap(urlParameters=> this.http.get<Credential[]>(`url with ${urlParameters}`) ) ); ... getCredentialList(newParams:ApiParameters): void { this.credentialParams$.next(newParams); }

Utilice el asunto para emitir los parámetros que necesite para su llamada a la API. Luego, el observable toma ese parámetro emitido y devuelve directamente el observable de solicitud HTTP.

 // credential-list.component.ts public credentials$: Observable<Credential[]> constructor( private credentialService: CredentialService, ) { this.credentials$ = this.credentialService.credentialListObv$.pipe( tap(() => {console.log("sub")}), ... ); } ngAfterViewInit(): void { this.credentialService.getCredentialList(apiParams); } // credential-list.component.html <mat-expansion-panel *ngFor="let credential of credentials$ | async; let i=index">

En el componente, solo nos suscribimos al servicio observable. En el ciclo de vida init, invocamos el método de servicio. Esto hace que su componente observable reaccione a la solicitud HTTP que se devolverá desde el servicio observable.

PD Está bien suscribirse a algo dentro de un servicio, si sabe que se completa observable (como solicitudes HTTP).

over 4 years ago · Santiago Trujillo Relatório

0

Debido a que usa BehaviourSubject , la primera emisión es el valor inicial de la misma. Luego, más tarde, en NgAfterViewInit , se suscribe a getCredentialList , que envía un nuevo valor al mismo BehaviourSubject .

Intente registrar los valores, en lugar de la cadena escrita:

tap((val) => {console.log(val)}),

El primero debe ser el predeterminado que usó cuando creó una instancia del sujeto ( this._credentialList$ = new BehaviorSubject(... )

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda