RxJS Interop : de quoi s'agit t-il ?

Lorsque la core team de Angular a annoncé l'arrivée du concept de Signals, plusieurs interrogations se sont soulevées quant à l'utilisation de la bibliothèque RxJS qui a été jusque-là un atout très important pour le framework Angular.

Est-ce que Angular Signals remplacera RxJS ?
Est-ce que Angular Signals et RxJS sont complémentaires ?
Quel sera l'avenir de RxJS dans Angular ?

Cet article vise à mettre la lumière sur ces interrogations ainsi que sur l'utilisation du package RxJS Interop que la core team de Angular a mis à disposition des développeurs.

Est-ce que Angular Signals remplacera RxJS ?

Angular Signals n'a pas pour but de remplacer RxJS. Le concept de Signals a été introduit afin d'optimiser le système de détection des changements dans nos composants Angular lorsque nous mettons à jour une variable ou un objet. Ce système a été conçu autour la bibliothèque Zone.js qui a démontré ces limites que j'ai eues à évoquer précédemment dans cet article Les nouveautés en Angular 16 (Partie 1)
Nous comprenons donc que Zone.js n'a rien avoir techniquement avec RxJS. Ce sont deux bibliothèques bien distinctes qui ont des buts différents.

Est-ce que Angular Signals et RxJS sont complémentaires ?

Maintenant que nous savons que Angular Signals n'est pas là pour remplacer RxJS, nous aborderons leur complémentarité.

Après avoir suivi plusieurs discussions entre les membres de la core team et ceux de la communauté Angular, je peux affirmer que oui 😃

En effet, les Signalspermettent une gestion d'état synchrone tandis que la bibliothèque RxJS le fait de manière asynchrone. La décision de choisir entre l'utilisation de RxJS ou celle de Signals dépendra donc de la complexité de nos opérations asynchrones et de l'environnement de développement existant. Pour des scénarios asynchrones complexes et des architectures basées sur des événements, RxJS offre des outils puissants. En revanche, pour des cas simples d'événements typiquement synchrone ou lorsqu'une meilleure intégration avec les fonctionnalités spécifiques d'Angular est souhaitée, les Signals peuvent être plus appropriés.

Quel sera l'avenir de RxJS dans Angular ?

Après être penché sur les deux premières interrogations qui constituaient des points d'ombre, il est légitime de se demander ce que nous réserve la core team Angular par rapport à l'utilisation de RxJS dans le futur.

L'objectif de la core team de Angular est de rendre optionnel l'installation de bibliothèque RxJS dans un projet Angular c'est-à-dire qu'à la création d'un projet Angular, la bibliothèque RxJS ne sera plus une dépendance installée par défaut. Toutefois, la core team est bien consciente de la puissance des fonctionnalités de RxJS. Pour faciliter la transition, ils ont mis en place le package RxJS Interop.

RxJS Interopd'Angular fournit des utilitaires utiles pour intégrer Angular Signals avec les observables RxJS. Voici quelques utilitaires ou helpers (en anglais) que nous offre cette nouvelle bibliothèque :

  • toSignal

La fonction toSignal permet de créer un signal qui écoute en permanence la valeur d'un Observable. Son comportement est similaire à celui du pipe async que nous utilisons dans nos templates HTML, mais il est plus flexible et peut être utilisé n'importe où dans une application. Voyons ensemble ce cas d'utilisation :

import { Component } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { interval } from 'rxjs';
@Component({
  template: `{{ counter() }}`,
})
export class Ticker {
  counterObservable = interval(1000);
  // Get a `Signal` representing the `counterObservable`'s value.
  counter = toSignal(this.counterObservable, {initialValue: 0});
}

Comme le pipe async, toSignal s'abonne immédiatement à l'Observable, ce qui peut entraîner des effets de bord. La souscription créée par toSignal se désabonne automatiquement de l'Observable donné lorsque le composant ou le service qui appelle toSignal est détruit. Ainsi, nous pouvons transformer un comportement asynchrone en synchrone en utilisant pleinement le potentiel des Signals.

Cependant,toSignalcrée une souscription. Il faut donc éviter de l'appeler plusieurs fois pour le mêmeObservable, et réutiliser le signal qu'il renvoie.

  • toObservable

A l'opposé de l'utilitaire toSignal, utilisez toObservable pour créer un Observable qui écoute en permanence la valeur d'un signal. La valeur du signal est surveillée par un effect qui transmet la valeur à l'Observable lorsqu'elle change. Voici un cas d'utilisation :

import { Component, signal } from '@angular/core';
@Component(...)
export class SearchResults {
  query: Signal<string> = inject(QueryService).query;
  query$ = toObservable(this.query);
  results$ = this.query$.pipe(
    switchMap(query => this.http.get('/search?q=' + query ))
  );
}

Lorsque le signal query change, l'observable query$ émet la dernière requête et déclenche une nouvelle demande HTTP. Dans l'exemple, on remarque l'utilisation deswitchMapqui est un opérateurRxJSce qui est normal car comme nous l'avons précédemment annoncé, pour les tâches asynchronous,RxJSdemeure très efficace.

Il est à noter qu'il reste deux autres utilitaires à savoir outputFromObservable et outputToObservable que nous verrons plus tard dans un nouvel article.

En somme, comme nous l'avons remarqué, pour comprendre l'utilité de RxJS Interop, il faut d'abord comprendre ce à quoi est destiné d'une part Angular Signals et d'autre part RxJS. Aujourd'hui, au travers de cet article, nous avons les idées claires de ce qu'il en sera du future de RxJS avec l'arrivée de Angular Signals.

Pour plus d'informations 👉 RxJS Interop

Did you find this article valuable?

Support Ezéchiel Amen AGBLA by becoming a sponsor. Any amount is appreciated!