Saltar al contenido

RxJS: takeUntil() ngOnDestroy() del componente angular

Hacemos una revisión completa cada uno de los escritos de nuestra web con la meta de mostrarte siempre información certera y certera.

Solución:

Podrías aprovechar un ReplaySubject para eso:

EDITAR: Diferente desde RxJS 6.x: Tenga en cuenta el uso de la pipe() método.

class myComponent 
  private destroyed$: ReplaySubject = new ReplaySubject(1);

  constructor(
    private serviceA: ServiceA,
    private serviceB: ServiceB,
    private serviceC: ServiceC) 

  ngOnInit() 
    this.serviceA
      .pipe(takeUntil(this.destroyed$))
      .subscribe(...);
    this.serviceB
      .pipe(takeUntil(this.destroyed$))
      .subscribe(...);
    this.serviceC
      .pipe(takeUntil(this.destroyed$))
      .subscribe(...);
  

  ngOnDestroy() 
    this.destroyed$.next(true);
    this.destroyed$.complete();
  

Esto solo es válido para RxJS 5.x y anteriores:

class myComponentOld 
  private destroyed$: ReplaySubject = new ReplaySubject(1);

  constructor(private serviceA: ServiceA) 

  ngOnInit() 
    this.serviceA
      .takeUntil(this.destroyed$)
      .subscribe(...);
  

  ngOnDestroy() 
    this.destroyed$.next(true);
    this.destroyed$.complete();
  

Utilizando el componentDestroyed() La función del paquete npm @w11k/ngx-componentdestroyed es, con mucho, la forma más fácil de usar takeUntil:

@Component(
  selector: 'foo',
  templateUrl: './foo.component.html'
)
export class FooComponent implements OnInit, OnDestroy 
  ngOnInit() 
    Observable.interval(1000)
      .takeUntil(componentDestroyed(this)) // <--- magic is here!
      .subscribe(console.log);
  

  ngOnDestroy() 

Aquí hay una versión de componentDestroyed() para incluir directamente en su código:

// Based on https://www.npmjs.com/package/ng2-rx-componentdestroyed
import  OnDestroy  from '@angular/core';
import  ReplaySubject  from 'rxjs/ReplaySubject';

export function componentDestroyed(component: OnDestroy) 
  const oldNgOnDestroy = component.ngOnDestroy;
  const destroyed$ = new ReplaySubject(1);
  component.ngOnDestroy = () => 
    oldNgOnDestroy.apply(component);
    destroyed$.next(undefined);
    destroyed$.complete();
  ;
  return destroyed$;

Bueno, esto se reduce a lo que quieres decir con cerrar una suscripción. Básicamente, hay dos formas de hacer esto:

  1. Usando un operador que completa la cadena (como takeWhile()).
  2. Darse de baja de la fuente Observable.

Es bueno saber que estos dos no son lo mismo.

Al usar por ejemplo takeWhile() haces que el operador envíe complete notificación que se propaga a sus observadores. Así que si defines:

...
.subscribe(..., ..., () => doWhatever());

Luego, cuando complete la cadena con, por ejemplo. takeWhile() los doWhatever() se llamará a la función.

Por ejemplo, podría verse así:

const Observable = Rx.Observable;
const Subject = Rx.Subject;

let source = Observable.timer(0, 1000);
let subject = new Subject();

source.takeUntil(subject).subscribe(null, null, () => console.log('complete 1'));
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 2'));
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 3'));

setTimeout(() => 
  subject.next();
, 3000);

Después de 3 segundos, se llamarán todas las devoluciones de llamada completas.

Por otro lado, cuando cancela la suscripción, está diciendo que ya no está interesado en los artículos producidos por la fuente Observable. Sin embargo, esto no significa que la fuente tenga que completarse. Simplemente ya no te importa.

Esto significa que puede recopilar todos Subscriptiones de .subscribe(...) llamadas y darte de baja todas a la vez:

let subscriptions = new Rx.Subscription();
let source = Observable.timer(0, 1000);

subscriptions.add(source.subscribe(null, null, () => console.log('complete 1')));
subscriptions.add(source.subscribe(null, null, () => console.log('complete 2')));
subscriptions.add(source.subscribe(null, null, () => console.log('complete 3')));

setTimeout(() => 
  subscriptions.unsubscribe();
, 3000);

Ahora, después de un retraso de 3 segundos, no se imprimirá nada en la consola porque cancelamos la suscripción y no se invocó una devolución de llamada completa.

Entonces, lo que quieras usar depende de ti y de tu caso de uso. Solo tenga en cuenta que cancelar la suscripción no es lo mismo que completar, aunque supongo que en su situación realmente no importa.

Sección de Reseñas y Valoraciones

Recuerda que te concedemos agregar una reseña si te fue preciso.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *