Convertir observables en señales en angular: lo que necesita saber

Angular v16 viene con un nuevo paquete llamado rxjs-interop
, que presenta la toSignal
función que convierte un observable en una señal. En este artículo, veremos más de cerca esta nueva característica y su uso.
Para comenzar a usar la toSignal
función, debemos importarla desde el @angular/core/rxjs-interop
módulo. Aquí hay un fragmento de código de ejemplo que demuestra su uso:
import { toSignal } from '@angular/core/rxjs-interop';
import { interval } from 'rxjs';
@Component({
standalone: true,
template:`{{ counter() }}`,
})
export class FooComponent {
counter$ = interval(1000);
counter = toSignal(this.counter$);
}
Vale la pena señalar que, a diferencia de la async
tubería, podemos leer el valor de la señal inmediatamente en nuestro componente, lo que puede producir undefined
.
Además, la toSignal
función se suscribe a lo observable inmediatamente , lo que puede provocar resultados no deseados en algunos casos si hay efectos secundarios.
Si tenemos un código que usa la async
canalización con una ngIf
directiva, se suscribirá al observable solo cuando rendericemos la plantilla.
@Component({
standalone: true,
template:`<div *ngIf="someCondition">
<div *ngFor="let item of source$ | async"></div>
</div>`,
})
export class FooComponent {
source$ = inject(Service).someMethod();
}
En caso de que queramos eliminar el undefined
tipo de nuestra señal resultante, tenemos dos opciones. El primero es pasar un valor inicial cuando tenemos un async
observable que no se dispara inmediatamente.
@Component({
standalone: true,
template:`{{ counter() }}`,
})
export class FooComponent {
counter$ = interval(1000);
counter = toSignal(this.counter$, { initialValue: 0 });
}
@Component({
standalone: true,
template:`{{ counter() }}`,
})
export class FooComponent {
counter$ = interval(1000).pipe(startWith(0));
counter = toSignal(this.counter$, { requireSync: true });
}
Cuando toSignal
se llama a la función, primero verifica para asegurarse de que se está llamando en un contexto de inyección . Si no, se lanzará un error. Eso significa que podemos usar la toSignal
función solo cuando la inject()
función está disponible, excepto en los casos en que usamos la manualCleanup
opción o pasamos injector
explícitamente.
La razón de esto es que Angular cancelará automáticamente la suscripción cuando se destruya el contexto de envoltura. Hace esto usando el nuevo OnDestroy
gancho que obtiene al usar la inject()
función o el proporcionado explícitamente injector
:
@Component({
selector: 'foo',
standalone: true,
template:`{{ counter() }}`,
})
export class FooComponent {
counter$ = interval(1000);
counter: Signal<number | undefined>;
private injector = inject(Injector);
ngOnInit() {
this.counter = toSignal(this.counter$, { injector: this.injector } );
}
}
@Component({
standalone: true,
template:`{{ counter() }}`,
})
export class FooComponent {
counter$ = interval(1000).pipe(take(3));
counter = toSignal(this.counter$, { manualCleanup: true });
}
@Component({
standalone: true,
template:`{{ counter() }}`,
})
export class FooComponent {
counter$ = interval(1000);
counter = toSignal(this.counter$, { initialValue: 0 });
ngOnInit() {
try {
this.counter();
} catch (e) {
console.log(e);
}
}
}
¡ Sígueme en Medium o Twitter para leer más sobre Angular y JS!