# 1. Introduction Avant toute chose, nous allons voir ou revoir certains concepts afin d’être sur un même niveau d’information. C’est nécessaire pour appréhender RxJS. ## 1.1. Quelques notions sur la programmation réactive La programmation réactive est un paradigme de programmation qui met l'accent sur la gestion des flux de données asynchrones et des événements. Elle vise à faciliter le développement d'applications réactives, c'est-à-dire des applications capables de réagir de manière dynamique aux changements de données en temps réel. Dans un contexte de programmation réactive, les données sont considérées comme des flux continus qui peuvent être observés et sur lesquels on peut réagir en temps réel. La programmation réactive se concentre sur la composition et la transformation de ces flux de données de manière déclarative, plutôt que d'utiliser des approches impératives traditionnelles. Voici quelques concepts clés de la programmation réactive : - Observables : Les observables représentent des flux de données asynchrones. Ils émettent des valeurs au fil du temps, et les observateurs peuvent souscrire à ces observables pour être notifiés lorsqu'une nouvelle valeur est émise. - Les observables sont une partie centrale de RxJS. Ils représentent des flux de données asynchrones et fournissent une manière de traiter ces flux de manière réactive. - Un Observable émet des valeurs au fil du temps, et les observateurs peuvent souscrire à cet Observable pour être notifiés lorsque de nouvelles valeurs sont émises. - Les observables peuvent être utilisés pour gérer divers types de flux de données, tels que des événements, des requêtes HTTP, des saisies utilisateur, etc. - Subscribers (ou observateurs) : Les observateurs sont des composants qui souscrivent à des observables pour écouter les valeurs émises par ceux-ci. Les observateurs peuvent réagir aux valeurs, appliquer des transformations ou effectuer des actions en fonction des événements émis par l'observable. - Les subscribers sont utilisés dans le contexte de la programmation réactive, notamment avec les observables. - Un subscriber est un observateur qui souscrit à un Observable pour écouter et réagir aux valeurs émises par cet Observable. - Lorsqu'un subscriber est souscrit à un Observable, il reçoit les valeurs émises par l'Observable, ainsi que d'autres notifications, telles que les erreurs ou la fin du flux de données. - Les subscribers sont plus flexibles que les listeners, car ils peuvent réagir à différentes étapes du flux de données, appliquer des opérations de transformation, filtrage ou combinaison, et gérer les erreurs de manière plus élaborée. - Opérateurs : Les opérateurs sont des fonctions qui permettent de transformer, filtrer, combiner ou manipuler les flux de données émis par les observables. Ils offrent des fonctionnalités puissantes pour gérer les flux de manière déclarative et modulaire. (Comme la méthode pipe) - Gestion des erreurs : La programmation réactive fournit des mécanismes avancés pour la gestion des erreurs dans les flux de données. Les erreurs peuvent être capturées, traitées et propagées de manière contrôlée. - Asynchronicité : La programmation réactive est particulièrement adaptée à la gestion des opérations asynchrones, telles que les requêtes HTTP, les événements de l'interface utilisateur, les mises à jour en temps réel, etc. Elle permet de gérer ces opérations de manière cohérente et simplifiée. En utilisant la programmation réactive, les développeurs peuvent créer des applications plus réactives, évolutives et maintenables. Elle permet de gérer de manière élégante les flux de données asynchrones, d'améliorer la gestion des événements et de faciliter la manipulation et la transformation des données en temps réel. RxJS est l'une des bibliothèques les plus populaires pour mettre en œuvre la programmation réactive dans des environnements JavaScript. ### 1.1.1. Je vais faire un aparté sur les listeners Les observables et les subscribers et les listeners sont des concepts utilisés dans des contextes différents pour gérer le flux de données asynchrones. Les Observables et les Listeners sont associés à la programmation réactive alors que les listeners : - Les listeners sont utilisés dans le contexte des événements, tels que les événements DOM dans les applications web. - Un listener est une fonction qui écoute un événement spécifique sur un élément (comme un bouton) et réagit lorsque cet événement se produit ( tels que les clics de bouton, les mouvements de souris, les saisies utilisateur, etc.). - Lorsque l'événement se déclenche, le listener est invoqué, et il peut exécuter un ensemble d'instructions prédéfinies. - Les listeners sont souvent enregistrés et désenregistrés dynamiquement en fonction de l'état de l'application ou des interactions utilisateur. > _Exemple :_ ```typescript= interface EventListener { (event: Event): void; } class Button { private clickListeners: EventListener[] = []; addClickListener(listener: EventListener) { this.clickListeners.push(listener); } removeClickListener(listener: EventListener) { const index = this.clickListeners.indexOf(listener); if (index !== -1) { this.clickListeners.splice(index, 1); } } click() { const event = new Event("click"); this.clickListeners.forEach((listener) => { listener(event); }); } } // Exemple d'utilisation const button = new Button(); const clickListener1: EventListener = (event) => { console.log("Écouteur 1 - Clic détecté !"); }; const clickListener2: EventListener = (event) => { console.log("Écouteur 2 - Clic détecté !"); }; button.addClickListener(clickListener1); button.addClickListener(clickListener2); button.click(); // Déclenche l'événement "click" button.removeClickListener(clickListener2); button.click(); // Déclenche l'événement "click" uniquement avec le premier écouteur ``` > _Dans cet exemple, nous avons une classe Button qui représente un bouton. La classe Button possède une liste d'écouteurs d'événements clickListeners. La méthode addClickListener permet d'ajouter un nouvel écouteur à la liste, tandis que removeClickListener permet de supprimer un écouteur de la liste._ > > _Lorsque la méthode click est appelée, un nouvel objet Event est créé avec le type d'événement "click". Ensuite, chaque écouteur dans la liste clickListeners est appelé avec cet objet Event._ > > _Dans l'exemple d'utilisation, nous créons deux écouteurs clickListener1 et clickListener2, puis nous les ajoutons à l'instance du bouton en utilisant la méthode addClickListener. Ensuite, nous appelons la méthode click sur le bouton, ce qui déclenche l'événement "click" et appelle chaque écouteur enregistré._ > > _Enfin, nous utilisons la méthode removeClickListener pour supprimer clickListener2 de la liste d'écouteurs, puis nous appelons à nouveau click, ce qui n'appellera que clickListener1._ > > _Lorsque vous exécutez ce code, vous verrez les messages correspondants affichés dans la console :_ ```shell= Écouteur 1 - Clic détecté ! Écouteur 2 - Clic détecté ! Écouteur 1 - Clic détecté ! ``` > _Cela démontre comment les écouteurs d'événements peuvent être utilisés pour détecter et réagir à des événements spécifiques, tels que des clics de bouton._ ## 1.2. Les promises Les Promises ne font pas partie intégrante du paradigme de programmation réactive. La programmation réactive se base principalement sur l'utilisation d'Observables pour gérer les flux de données asynchrones. Cependant, il est possible d'utiliser les Promises en conjonction avec la programmation réactive dans certaines situations. Dans certaines bibliothèques de programmation réactive, notamment RxJS (la bibliothèque RxJS étant un exemple populaire de programmation réactive en JavaScript), il existe des utilitaires qui permettent de convertir des Promises en Observables. Cela peut être utile lorsque vous avez déjà des Promises existantes ou lorsque vous devez interagir avec des bibliothèques ou des API qui utilisent des Promises. De plus, les Promises peuvent être utilisées de manière indépendante de la programmation réactive pour gérer des opérations asynchrones ponctuelles et obtenir des résultats futurs. Promises : - Une Promise représente une valeur qui peut être disponible immédiatement, dans le futur ou jamais. - Elle est utilisée pour gérer une seule valeur asynchrone ou une opération unique. - Une Promise a deux états possibles : résolue (fulfilled) avec une valeur ou rejetée (rejected) avec une raison d'échec. - Une fois que la Promise est résolue ou rejetée, elle ne peut pas être annulée. - Les Promises sont basées sur un modèle de résolution unique. Une fois résolue ou rejetée, une Promise ne peut pas être réutilisée. - Les Promises sont gérées par des méthodes telles que .then() et .catch(), qui permettent de réagir aux résultats ou aux échecs de la Promise. - Elles offrent une syntaxe plus expressive et une meilleure gestion des erreurs que les callbacks traditionnels. Exemple : ```typescript= function delay(ms: number): Promise<void> { return new Promise((resolve) => { setTimeout(resolve, ms); }); } console.log("Avant la promesse"); delay(2000) .then(() => { console.log("La promesse est résolue !"); }) .catch((error) => { console.error("Une erreur s'est produite :", error); }) .finally(() => { console.log("La promesse est terminée."); }); console.log("Après la promesse"); ``` > _Dans cet exemple, la fonction delay retourne une promesse qui se résout après un délai spécifié en millisecondes. La fonction setTimeout est utilisée pour simuler cette attente._ > > _Lorsque la promesse est résolue, la fonction de rappel passée à then est exécutée, affichant "La promesse est résolue !". Si une erreur se produit pendant l'exécution de la promesse, la fonction de rappel passée à catch est appelée avec l'erreur correspondante. Enfin, la fonction de rappel passée à finally est exécutée, indépendamment de la résolution ou du rejet de la promesse._ > > _Lorsque vous exécutez ce code, vous verrez que la phrase "Avant la promesse" est affichée en premier, puis après un délai de 2 secondes, la phrase "La promesse est résolue !" est affichée. Ensuite, la phrase "La promesse est terminée." est affichée, et enfin, la phrase "Après la promesse" est affichée. Cela démontre la nature asynchrone des promesses et comment elles peuvent être utilisées pour gérer des opérations retardées ou des tâches asynchrones._ # 2. Présentation de RxJS ## 2.1. Qu'est-ce que RxJS ? RxJS (Reactive Extensions for JavaScript) est une bibliothèque JavaScript de programmation réactive qui permet de gérer facilement les flux de données asynchrones et de créer des applications réactives. Elle est basée sur le patron de conception Observable, qui fournit une approche élégante pour la gestion des événements, des requêtes HTTP, des opérations asynchrones et d'autres flux de données. RxJS est la version JavaScript de la bibliothèque Reactive Extensions (Rx) disponible dans différents langages de programmation tels que C#, Java, Python, etc. Elle a été développée pour permettre aux développeurs JavaScript de tirer parti des principes de la programmation réactive et de bénéficier de sa puissance et de sa flexibilité. Les principaux concepts de RxJS sont les suivants : - Observables : Les Observables représentent des flux de données asynchrones. Ils émettent des valeurs au fil du temps, que ce soit des événements, des résultats de requêtes HTTP, des saisies utilisateur, etc. Les Observables peuvent être utilisés pour gérer et transformer ces flux de manière réactive. - Opérateurs : Les Opérateurs sont des fonctions qui permettent de manipuler, transformer, filtrer et combiner les flux de données émis par les Observables. Ils permettent d'effectuer des opérations telles que la cartographie (map), le filtrage (filter), la réduction (reduce), la fusion (merge), etc. Les opérateurs offrent une grande flexibilité pour traiter les flux de données de manière déclarative. - Souscriptions (Subscriptions) : Les Souscriptions (ou subscriptions) sont utilisées pour observer les valeurs émises par les Observables. Lorsqu'un Observateur (ou Observer) s'abonne à un Observable, il reçoit les valeurs émises par celui-ci, ainsi que d'autres notifications telles que les erreurs ou la fin du flux de données. Les souscriptions peuvent être gérées pour contrôler le cycle de vie des Observateurs et libérer les ressources lorsque cela est nécessaire. - Gestion des erreurs : RxJS fournit des mécanismes avancés pour gérer les erreurs dans les flux de données. Les erreurs peuvent être capturées, traitées et propagées de manière contrôlée, permettant une gestion robuste des erreurs dans les applications réactives. RxJS offre une grande variété d'opérateurs prédéfinis, ainsi que la possibilité de créer des opérateurs personnalisés pour répondre aux besoins spécifiques des applications. Il est utilisé dans de nombreux frameworks et bibliothèques JavaScript populaires, tels que Angular, React, Vue.js, etc., pour faciliter le développement d'applications réactives, performantes et maintenables. ## 2.2. Pourquoi utiliser RxJS ? Il y a plusieurs raisons pour lesquelles on pourrait choisir d'utiliser RxJS dans le développement d'applications JavaScript : - Gestion des flux de données asynchrones : RxJS offre une approche simplifiée pour gérer les flux de données asynchrones tels que les événements, les requêtes HTTP, les interactions utilisateur, etc. Il permet de traiter ces flux de manière réactive et de réagir de manière cohérente aux changements de données en temps réel. - Programmation déclarative : RxJS favorise la programmation déclarative, ce qui signifie que vous décrivez ce que vous souhaitez obtenir plutôt que de détailler comment l'obtenir. Les opérateurs RxJS permettent de manipuler et de transformer les flux de données de manière déclarative, rendant le code plus lisible, modulaire et facilement testable. - Gestion avancée des erreurs : RxJS propose des mécanismes sophistiqués pour gérer les erreurs dans les flux de données. Il permet de capturer, de traiter et de propager les erreurs de manière contrôlée, ce qui facilite la gestion des scénarios d'erreur et la prise de décisions appropriées. - Composition des flux de données : Les Observables de RxJS peuvent être combinés, filtrés, transformés et concaténés de manière flexible grâce aux opérateurs RxJS. Cela permet de créer des pipelines de traitement des données complexes en composant les opérations souhaitées, ce qui simplifie la logique du code et le rend plus modulaire et réutilisable. - Gestion de la concurrence : RxJS propose des opérateurs pour gérer les opérations concurrentes, telles que la gestion des appels parallèles aux API, la fusion de flux de données asynchrones et la synchronisation de tâches asynchrones. Cela permet de gérer facilement des scénarios où plusieurs sources de données doivent être combinées ou synchronisées. - Large adoption et support communautaire : RxJS est largement utilisé dans la communauté JavaScript, en particulier dans des frameworks populaires tels que Angular. Il dispose d'une documentation complète, de nombreux exemples et d'une communauté active qui partage des connaissances et des bonnes pratiques. En résumé, RxJS offre une approche puissante et simplifiée pour gérer les flux de données asynchrones, la gestion des erreurs, la composition des opérations et la gestion de la concurrence. Il facilite le développement d'applications réactives, modulaires, réutilisables et maintenables, tout en bénéficiant d'une adoption étendue et d'un soutien actif de la communauté. ## 2.3. Contexte et utilisation Et c’est dans un contexte actuel d’applications web modernes, que la gestion des données asynchrones et les interactions en temps réel est devenue primordiale. Les applications doivent réagir rapidement aux événements utilisateur, aux mises à jour de données distantes et aux changements d'état, tout en maintenant une interface utilisateur fluide et réactive. C'est là qu'intervient RxJS. Avec sa syntaxe concise et sa richesse de fonctionnalités, RxJS offre une solution puissante pour gérer les flux de données asynchrones et créer des applications réactives. Que ce soit pour traiter des événements DOM, des appels réseau, des opérations asynchrones ou des flux de données complexes, RxJS facilite la gestion de ces scénarios en fournissant des outils de haut niveau. RxJS trouve une large utilisation dans le développement d'applications JavaScript modernes, notamment dans les frameworks tels que Angular, React, Vue.js, et bien d'autres. Voici quelques cas d'utilisation courants où RxJS brille : - Gestion des événements : RxJS permet de gérer facilement les événements DOM et les interactions utilisateur réactives. Il offre une syntaxe expressive pour écouter et réagir aux événements, ce qui facilite la mise en place de fonctionnalités interactives dans les applications. - Requêtes HTTP asynchrones : RxJS facilite la gestion des appels réseau asynchrones tels que les requêtes HTTP. Il permet de créer des flux de données asynchrones et d'appliquer des opérations de transformation et de filtrage pour gérer les réponses et les erreurs de manière réactive. - Flux de données complexes : Les applications modernes traitent souvent des flux de données complexes provenant de différentes sources. RxJS offre des opérateurs puissants pour combiner, filtrer, transformer et synchroniser ces flux de données, simplifiant ainsi la logique du code et améliorant la maintenabilité. - Programmation réactive : RxJS facilite l'adoption du paradigme de programmation réactive. Il permet de gérer les flux de données asynchrones de manière réactive et de réagir aux changements de manière cohérente et efficace. Cela améliore la réactivité des applications, la gestion des erreurs et la composition des opérations. - Tests unitaires : RxJS facilite également les tests unitaires des applications réactives. Sa nature déclarative et ses fonctionnalités d'opérateurs permettent de créer des tests clairs et concis pour vérifier le comportement des flux de données et s'assurer de la cohérence des résultats. En conclusion, RxJS est largement utilisé pour gérer les flux de données asynchrones et créer des applications réactives dans le contexte des applications web modernes. Son utilisation s'étend à plusieurs domaines, de la gestion des événements aux requêtes HTTP asynchrones en passant par la manipulation de flux de données complexes. En adoptant RxJS, les développeurs peuvent bénéficier d'une gestion simplifiée des données asynchrones, d'une meilleure réactivité de l'application et d'une facilité de test accrue. # 3. Les bases de RxJS ## 3.1. Observables ### 3.1.1. Qu'est-ce qu'un Observable ? Un Observable est un concept clé de la programmation réactive et représente un flux de données asynchrones sur une période de temps. Il peut émettre zéro, un ou plusieurs éléments (valeurs), ainsi que des erreurs ou une notification de complétion. Les Observables sont au cœur de RxJS (Reactive Extensions for JavaScript) et sont utilisés pour gérer et manipuler les flux de données asynchrones de manière réactive. > _Pour info : Dans le contexte de la programmation réactive, une notification de complétion (completion notification en anglais) est un signal émis par un Observable pour indiquer que la séquence d'émissions de données est terminée._ > > _Lorsqu'un Observable a émis toutes ses valeurs et n'a plus rien à émettre, il envoie une notification de complétion pour signaler qu'il a terminé son flux de données. Cela peut être utile pour indiquer à d'autres parties du code que le traitement des données est terminé ou pour effectuer des opérations de nettoyage ou de finalisation._ > > _Une notification de complétion est représentée par une émission spéciale appelée "complete" (ou "complete event"). Elle est généralement suivie d'une désinscription automatique des abonnés à l'Observable, car il n'y a plus rien à émettre._ ```typescript import { Observable } from 'rxjs'; const numbers$ = new Observable<number>(subscriber => { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete(); }); const subscription = numbers$.subscribe( (value) => console.log(value), (error) => console.error(error), () => console.log('Observable complete') ); ``` > _Dans cet exemple, nous créons un Observable numbers$ qui émet les valeurs 1, 2 et 3 à l'aide de la méthode next(). Après avoir émis toutes les valeurs, nous envoyons une notification de complétion en appelant la méthode complete()._ > > _Lorsque nous nous abonnons à l'Observable en utilisant la méthode subscribe(), nous fournissons trois fonctions de rappel : une pour les valeurs émises, une pour les erreurs éventuelles et une pour la notification de complétion. Dans cet exemple, la fonction de rappel pour la notification de complétion affiche simplement un message indiquant que le flux de données est terminé._ > > _Il est important de noter qu'une fois la notification de complétion émise, aucun autre élément ne sera émis par l'Observable. Cela marque la fin du flux de données et permet aux abonnés de prendre des mesures appropriées en conséquence._ Voici les caractéristiques principales d'un Observable : - Flux de données : Un Observable émet une séquence de valeurs au fil du temps. Ces valeurs peuvent être de n'importe quel type (nombre, chaîne, objet, etc.) et représentent les événements ou les données émis par l'Observable. - Asynchronisme : Les valeurs émises par un Observable peuvent être produites de manière asynchrone, c'est-à-dire qu'elles peuvent provenir de requêtes réseau, de manipulations d'événements, de saisies utilisateur, etc. L'Observable gère de manière transparente la gestion asynchrone des valeurs émises. - Possibilité d'erreur : Un Observable peut émettre des erreurs lorsqu'une opération asynchrone échoue ou qu'une condition d'erreur est rencontrée. Les erreurs peuvent être gérées, propagées ou transformées en fonction des besoins de l'application. - Notification de complétion : Un Observable peut émettre une notification de complétion, indiquant la fin du flux de données. Cela permet de détecter lorsque toutes les valeurs ont été émises et que l'Observable ne produira plus de nouvelles valeurs. - Gestion des souscriptions : Pour observer les valeurs émises par un Observable, il faut s'abonner à celui-ci. L'abonnement (subscription) permet de définir les fonctions de rappel (callbacks) qui seront invoquées lors de l'émission de valeurs, d'erreurs ou de la notification de complétion. Il est également possible de gérer le cycle de vie des abonnements en les annulant ou en les libérant pour éviter les fuites de mémoire. Les Observables offrent des opérations puissantes pour la manipulation et la transformation des flux de données. Les développeurs peuvent utiliser des opérateurs RxJS tels que map, filter, merge, reduce et bien d'autres pour transformer, combiner, filtrer ou réduire les flux de données émis par les Observables. En résumé, un Observable est un concept clé de RxJS qui représente un flux de données asynchrones émettant des valeurs, des erreurs et une notification de complétion au fil du temps. Il permet de gérer et de manipuler les flux de données de manière réactive en utilisant des opérateurs pour effectuer des transformations et des combinaisons complexes. ### 3.1.2. Création d'un Observable Pour créer un Observable dans RxJS, vous pouvez utiliser la fonction Observable.create() ou l'un des opérateurs de création fournis par RxJS. Voici quelques exemples de création d'Observables : 1. Création avec Observable.create() : ```typescript import { Observable } from 'rxjs'; const observable$ = Observable.create((observer) => { observer.next('Première valeur'); observer.next('Deuxième valeur'); // Gestion des erreurs // observer.error('Une erreur s'est produite'); // Notification de complétion observer.complete(); // Netttoyage (facultatif) return () => { // Code de nettoyage }; }); ``` 2. Création avec un opérateur de création : ```typescript import { of } from 'rxjs'; const observable$ = of('Première valeur', 'Deuxième valeur'); ``` 3. Création avec un opérateur de création : ```typescript import { fromEvent } from 'rxjs'; const button = document.querySelector('button'); const observable$ = fromEvent(button, 'click'); ``` 4. Création avec un opérateur de création : ```typescript import { ajax } from 'rxjs/ajax'; // Using tio fetch response from an API const observable1$ = ajax.getJSON('https://api.exemple.com/data'); // Using to fetch data from an API const observable2$ = ajax.getJSON('https://api.exemple.com/data'); ``` 5. Création avec un opérateur de création : ```typescript import { from } from 'rxjs'; const observable$ = from([1, 2, 3, 4, 5]); ``` ### 3.1.3. Souscription à un Observable Une fois que vous avez créé un Observable, vous pouvez vous y abonner (subscribe) pour observer les valeurs émises, gérer les erreurs et détecter la notification de complétion. Voici un exemple d'abonnement à un Observable créé précédemment : ```typescript const subscription = observable$.subscribe( { next: (value) => { console.log(value); }, error: (error) => { console.error(error); }, complete: () => { console.log('Observable complete'); } }); ``` N'oubliez pas de gérer le cycle de vie de l'abonnement en le désabonnant lorsque vous n'avez plus besoin d'observer les valeurs émises par l'Observable. Vous pouvez le faire en appelant la méthode unsubscribe() sur l'objet subscription retourné par la méthode subscribe(). Ces exemples vous donnent un aperçu de différentes façons de créer des Observables en utilisant RxJS. En fonction de votre cas d'utilisation spécifique, vous pouvez choisir l'approche la mieux adaptée à votre application. Lorsque vous appelez la méthode subscribe() sur un Observable dans RxJS, vous pouvez fournir un objet d'observation (observer) qui spécifie les callbacks que vous souhaitez utiliser pour gérer les différentes notifications émises par l'Observable. Voici les callbacks disponibles : 1. __next__ : Ce callback est appelé lorsque l'Observable émet une nouvelle valeur. Il reçoit cette valeur en tant que paramètre. Vous pouvez utiliser ce callback pour effectuer des opérations ou des traitements spécifiques sur chaque valeur émise. Exemple : ```typescript observable.subscribe({ next: (value) => { console.log('Valeur émise : ', value); } }); ``` 2. __error__ : Ce callback est appelé lorsque l'Observable émet une erreur. Il reçoit cette erreur en tant que paramètre. Vous pouvez utiliser ce callback pour gérer les erreurs, effectuer des actions de récupération ou afficher des messages d'erreur à l'utilisateur. Exemple : ```typescript observable.subscribe({ error: (error) => { console.error(`Une erreur s'est produite : `, error); } }); ``` 3. complete: Ce callback est appelé lorsque l'Observable émet une notification de complétion. Il ne prend aucun paramètre. Vous pouvez utiliser ce callback pour effectuer des actions de nettoyage, mettre à jour l'interface utilisateur ou déclencher d'autres actions une fois que l'Observable a terminé d'émettre des valeurs. Exemple : ```typescript observable.subscribe({ complete: () => { console.log('Observable complete'); } }); ``` Vous pouvez fournir un ou plusieurs de ces callbacks lors de l'appel à subscribe(), en fonction de vos besoins spécifiques. Si vous ne souhaitez pas gérer certaines notifications, vous pouvez simplement les omettre. Il est important de noter que lorsqu'un Observable émet une erreur ou une notification de complétion, il ne produira plus de valeurs supplémentaires. C'est pourquoi il est recommandé de gérer les erreurs et la complétion de manière appropriée pour éviter les fuites de ressources ou les comportements inattendus dans votre application. ### 3.1.4. Unsusbscribe De plus, la méthode subscribe() retourne un objet de type Subscription, qui représente l'abonnement à l'Observable. Cet objet peut être utilisé ultérieurement pour annuler (unsubscribe) l'abonnement en appelant la méthode unsubscribe(). Cela est utile pour gérer le cycle de vie de l'abonnement et éviter les fuites de mémoire. ```typescript import { interval } from 'rxjs'; // Création d'un Observable qui émet une valeur toutes les 1000 ms const observable$ = interval(1000); // Abonnement à l'Observable et stocka de l'objet Subscription retourné const subscription = observable$.subscribe((value) => { console.log('Valeur émise : ', value); }); // Après 5 secondes, on se désabonne de l'Observable setTimeout(() => { subscription.unsubscribe(); console.log('Désabonnement effectué'); }, 5000); ``` Dans cet exemple, nous créons un Observable interval qui émet une valeur toutes les 1000 millisecondes (1 seconde). Ensuite, nous nous abonnons à cet Observable et stockons l'objet Subscription retourné par la méthode subscribe(). Après 5 secondes, nous appelons la méthode unsubscribe() sur l'objet Subscription pour nous désabonner de l'Observable. Cela arrête la réception des valeurs émises par l'Observable. Lorsque nous appelons unsubscribe(), le flux de données de l'Observable est coupé et les ressources associées à l'abonnement sont libérées. Cela permet d'éviter les fuites de mémoire et d'arrêter la consommation des valeurs de l'Observable. Dans l'exemple, une fois que le désabonnement est effectué, nous affichons un message indiquant que le désabonnement a été réalisé avec succès. Il est important de noter que le désabonnement est une étape essentielle pour gérer le cycle de vie des abonnements aux Observables, en particulier lorsque vous n'avez plus besoin de recevoir de nouvelles valeurs émises. Cela permet d'éviter les fuites de mémoire et d'optimiser les performances de votre application parce qu’il va : - Désinscrire les "callbacks" : next, error et complete - Détruire l'Observable (c'est à dire interrompre les traitements effectués par l'Observable) si celui-ci est de type "cold" - Éventuellement libérer la mémoire car en désinscrivant les "callbacks", le "garbage collector" libérera la mémoire occupée par les objets référencés dans les "callbacks" (s'ils ne sont plus référencés ailleurs) L'unsubscribe s’il n’est pas fait explicitement, se fait généralement : - Lors de la destruction d'un composant via le "lifecycle hook" ngOnDestroy, - Lorsqu'un Observable doit en remplacer un autre (e.g. : lancement d'une nouvelle recherche par un utilisateur ou rafraichissement du contenu). S’il est appelé explicitement et dans certains cas, nous préférons l'utilisation du "pipe" async que nous verrons plus tard ou alors des "helpers" tels que Rx-Scavenger. #### 3.1.4.1. Rx-Scavenger Rx-Scavenger est un "Garbage Collector" de Subscription RxJS pour Angular. https://github.com/wishtack/wishtack-steroids/tree/master/packages/rx-scavenger Il permet d'unsubscribe automatiquement au remplacement d'une subscription ou à la destruction d'un composant. ```shell yarn add @wishtack/rx-scavenger ``` ```typescript import {Scavenger} from '@wishtack/rx-scavenger'; @Component({ ... }) export class MyComponent implements OnInit, OnDestroy { private _scavenger = new Scavenger(this); constructor(private _weatherStation: WeatherStation) {} ngOnInit() { this._weatherStation .getWeather('Rennes') .pipe(this._scavenger.collect()) .subscribe((weather) => { ... }); } ngOnDestroy() { // Appel à la méthode unsubscribe() de Scavenger. this._scavenger.unsubscribe(); } } ``` ## 3.2. Les opérateurs Les opérateurs RxJS sont des fonctions qui permettent de manipuler, transformer, combiner ou filtrer les flux de données émis par les Observables dans RxJS (Reactive Extensions for JavaScript). Ils constituent une partie essentielle de la boîte à outils RxJS et offrent une puissance et une expressivité supplémentaires pour travailler avec les flux de données de manière réactive. Les opérateurs RxJS peuvent être divisés en plusieurs catégories, chacune offrant des fonctionnalités spécifiques : 1. Opérateurs de transformation : Ces opérateurs permettent de transformer les valeurs émises par un Observable en appliquant des fonctions de transformation. Par exemple, l'opérateur map permet de modifier chaque valeur émise en appliquant une fonction de transformation. 2. Opérateurs de filtrage : Ces opérateurs permettent de filtrer les valeurs émises par un Observable en fonction de certaines conditions. Par exemple, l'opérateur filter permet de ne conserver que les valeurs qui satisfont une condition donnée. 3. Opérateurs de combinaison : Ces opérateurs permettent de combiner les valeurs émises par plusieurs Observables en un seul flux de données. Par exemple, l'opérateur merge permet de fusionner plusieurs Observables en un seul Observable qui émettra toutes les valeurs de manière intercalée. Était focus sur la méthode of qui aidera dans les exemples suivants : La méthode `of` de RxJS permet de créer un Observable qui émet une séquence de valeurs spécifiées. Elle prend en paramètre un ou plusieurs arguments correspondant aux valeurs à émettre. Voici un exemple d'utilisation de la méthode of : ```typescript import { of } from 'rxjs'; const observable$ = of(1, 2, 3, 'four', [5, 6], { prop: 'value'}); observable$.subscribe((value) => { console.log('Valeur émise : ', value); }); ``` Dans cet exemple, nous utilisons la méthode of pour créer un Observable qui émet plusieurs valeurs. Nous passons les valeurs 1, 2, 3, 'four', [5, 6] et { prop: 'value' } en tant qu'arguments de la méthode of. Lorsque nous nous abonnons à cet Observable et recevons les valeurs émises, nous utilisons une fonction callback dans la méthode subscribe pour afficher chaque valeur émise. Résultat : ```shell Valeur émise : 1 Valeur émise : 2 Valeur émise : 3 Valeur émise : four Valeur émise : [ 5, 6 ] Valeur émise : { prop: 'value' } ``` Comme vous pouvez le voir, la méthode of permet de créer facilement un Observable émettant une séquence de valeurs spécifiques. Cela peut être utile lorsque vous souhaitez émettre des valeurs prédéfinies sans les récupérer à partir d'une source externe telle qu'une requête HTTP ou un événement. ### 3.2.1. Transformation des données Voici un exemple d'utilisation de l'opérateur de transformation `map` de RxJS : ```typescript import { of } from 'rxjs'; import { map } from 'rxjs/operators'; const observable$ = of(1, 2, 3); observable$ .pipe(map((value) => value * 2)) .subscribe((result) => { console.log('Valeur transformée : ', result); }); ``` Dans cet exemple, nous créons un Observable à l'aide de la méthode of qui émet les valeurs 1, 2 et 3. Ensuite, nous utilisons l'opérateur map en le chaînant à l'aide de la méthode pipe sur l'Observable. L'opérateur map transforme chaque valeur émise par l'Observable en multipliant la valeur par 2. Ainsi, chaque valeur émise est transformée en sa valeur d'origine multipliée par 2. Ensuite, nous nous abonnons à l'Observable transformé et utilisons une fonction callback dans la méthode subscribe pour afficher chaque valeur transformée. Résultat : ```shell Valeur transformée : 2 Valeur transformée : 4 Valeur transformée : 6 ``` Comme vous pouvez le voir, l'opérateur map permet de modifier les valeurs émises par l'Observable en appliquant une fonction de transformation. Cela offre une flexibilité pour effectuer des opérations spécifiques sur les valeurs émises, telles que les manipuler, les formater ou les filtrer. Il existe de nombreux autres opérateurs de transformation dans RxJS, tels que pluck, mapTo, scan, flatMap, switchMap, etc., qui offrent différentes fonctionnalités pour transformer les flux de données en fonction de vos besoins spécifiques. ### 3.2.2. Filtrage des données Voici un exemple d'utilisation de l'opérateur de filtrage filter de RxJS : ```typescript import { of } from 'rxjs'; import { filter } from 'rxjs/operators'; const observable$ = of(1, 2, 3, 4, 5, 6); observable$ .pipe(filter((value) => value % 2 === 0)) .subscribe((result) => { console.log('Valeur filtrée : ', result); }); ``` Dans cet exemple, nous créons un Observable à l'aide de la méthode of qui émet les valeurs 1, 2, 3, 4 et 5. Ensuite, nous utilisons l'opérateur filter en le chaînant à l'aide de la méthode pipe sur l'Observable. L'opérateur filter permet de filtrer les valeurs émises par l'Observable en fonction d'une condition donnée. Dans cet exemple, nous utilisons la condition value % 2 === 0 pour filtrer uniquement les valeurs paires. Ainsi, seules les valeurs qui satisfont la condition seront émises et propagées à l'abonné suivant l'opérateur filter. Ensuite, nous nous abonnons à l'Observable filtré et utilisons une fonction callback dans la méthode subscribe pour afficher chaque valeur filtrée. Résultat : ```shell Valeur filtrée : 2 Valeur filtrée : 4 Valeur filtrée : 6 ``` Comme vous pouvez le voir, l'opérateur filter permet de sélectionner sélectivement les valeurs émises par l'Observable en fonction d'une condition spécifiée. Cela vous permet de contrôler quelles valeurs sont incluses dans le flux de données en fonction de vos critères de filtrage. RxJS propose d'autres opérateurs de filtrage tels que take, first, last, distinct, debounceTime, etc., qui offrent différentes fonctionnalités pour filtrer les flux de données en fonction de vos besoins spécifiques. ### 3.2.3. Combinaison des données Voici un exemple d'utilisation de l'opérateur de combinaison merge de RxJS : ```typescript import { interval } from 'rxjs'; import { merge } from 'rxjs/operators'; const observable1$ = interval(1000); const observable2$ = interval(500); observable1$ .pipe(merge(observable2$)) .subscribe((result) => { console.log('Valeur combinée : ', result); }); ``` Dans cet exemple, nous créons deux Observables : observable1 et observable2. observable1 émet une valeur toutes les 1000 millisecondes (1 seconde), tandis que observable2 émet une valeur toutes les 500 millisecondes (0,5 seconde). Ensuite, nous utilisons l'opérateur merge en le chaînant à l'aide de la méthode pipe sur observable1. L'opérateur merge fusionne les valeurs émises par plusieurs Observables en un seul flux de données. Ainsi, les valeurs de observable1 et observable2 sont combinées et émises de manière intercalée. En nous abonnant à l'Observable résultant de l'opérateur merge, nous utilisons une fonction callback dans la méthode subscribe pour afficher chaque valeur combinée. Résultat : ```shell Valeur combinée : 0 Valeur combinée : 0 Valeur combinée : 1 Valeur combinée : 2 Valeur combinée : 1 Valeur combinée : 3 Valeur combinée : 2 Valeur combinée : 4 Valeur combinée : 3 Valeur combinée : 5 ``` Comme vous pouvez le voir, l'opérateur merge permet de combiner les flux de données émis par plusieurs Observables en un seul flux. Les valeurs des Observables sont émises de manière intercalée, en fonction de l'ordre d'arrivée. RxJS propose d'autres opérateurs de combinaison tels que concat, zip, combineLatest, withLatestFrom, etc., qui offrent différentes fonctionnalités pour combiner les flux de données en fonction de vos besoins spécifiques. Pour info : La méthode interval de RxJS permet de créer un Observable qui émet une séquence de nombres entiers incrémentés à intervalles réguliers. Dans cet exemple, nous avons spécifié 1000, ce qui signifie que l'Observable émettra un nombre entier toutes les 1000 millisecondes (1 seconde) et un second 500, ce qui signifie que l'Observable émettra un nombre entier toutes les 500 millisecondes (0.5 seconde). Ainsi, chaque demi seconde, une nouvelle valeur sera émise et propagée aux abonnés. ### 3.2.4. Gestion des erreurs Voici un exemple d'utilisation de l'opérateur de gestion d'erreur catchError de RxJS : ```typescript import { of, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; const observable$ = of(1, 2, 3, 'four', 5); observable$.pipe( map((value) => { if (typeof value !== 'number') { throw new TypeError(`La valeur n'est pas un nombre`); } return value * 2; }), catchError((error) => { console.log('Erreur detectée : ', error.message); return of('Valeur de remplacement'); }) ).subscribe((result) => { console.log('Valeur transformée : ', result); }); ``` Dans cet exemple, nous utilisons l'opérateur catchError en le chaînant à l'aide de la méthode pipe sur l'Observable. L'opérateur catchError permet de gérer les erreurs émises par l'Observable et de les remplacer par des valeurs de substitution ou de les traiter d'une autre manière. Avant d'appliquer l'opérateur catchError, nous utilisons également l'opérateur map pour doubler les valeurs numériques émises par l'Observable. Cependant, si une valeur non numérique est émise, nous lançons une erreur à l'aide de throw new Error(). L'opérateur catchError intercepte cette erreur et exécute la fonction de rappel spécifiée. Dans notre exemple, nous affichons simplement le message d'erreur à l'aide de console.log, puis nous remplaçons l'erreur par une valeur de remplacement en utilisant return of('Valeur de remplacement'). Enfin, nous nous abonnons à l'Observable après l'application de l'opérateur catchError, et nous utilisons une fonction callback dans la méthode subscribe pour afficher le résultat. Résultat : ```shell Résultat : 2 Résultat : 4 Résultat : 6 Erreur detectée : La valeur n'est pas un nombre Résultat : Valeur de remplacement Résultat : 10 ``` Comme vous pouvez le voir, l'opérateur catchError permet de gérer les erreurs émises par l'Observable et de prendre des mesures appropriées, telles que les remplacer par des valeurs de substitution ou effectuer un traitement spécifique. Cela vous permet de contrôler le flux d'exécution même en cas d'erreur, en évitant que l'erreur ne se propage jusqu'à l'abonné et en fournissant une alternative appropriée à la suite du flux de données. # 4. Exemples pratiques ## 4.1. Gestion des événements ### 4.1.1. Exemple de clics de bouton Voici un exemple pratique d'utilisation de RxJS pour gérer les événements de clic sur un bouton : ```typescript import { fromEvent } from 'rxjs'; const button = document.getElementById('button'); const clickObservable = fromEvent(button, 'click'); clickObservable.subscribe((event) => { console.log('Clic sur le bouton détecté !'); }); ``` Dans cet exemple, nous utilisons la fonction fromEvent de RxJS pour créer un Observable à partir de l'événement de clic sur un bouton. Nous sélectionnons le bouton à l'aide de la méthode getElementById en lui passant l'identifiant 'myButton'. Ensuite, nous passons le bouton et le nom de l'événement 'click' à la fonction fromEvent. Cela crée un Observable qui émettra une valeur chaque fois que l'événement de clic est déclenché sur le bouton. Nous nous abonnons ensuite à cet Observable en utilisant la méthode subscribe et en fournissant une fonction callback qui sera exécutée chaque fois que l'événement de clic se produit. Dans cet exemple, nous affichons simplement un message dans la console lorsque le clic est détecté. Ainsi, chaque fois que l'utilisateur clique sur le bouton, le message "Clic sur le bouton détecté !" sera affiché dans la console. Vous pouvez bien sûr ajouter d'autres opérations d'opérateurs RxJS, comme les opérateurs de filtrage ou de transformation, pour traiter les événements de manière plus avancée en fonction de vos besoins spécifiques. ### 4.1.2. Exemple de saisie de texte Voici un exemple pratique d'utilisation de RxJS pour gérer les événements de saisie de texte dans un champ de texte : ```typescript import { fromEvent } from 'rxjs'; import { map, debounceTime } from 'rxjs/operators'; const input = document.getElementById('myInput'); const inputObservable = fromEvent(input, 'input').pipe( map((event) => event.target.value), debounceTime(300) ); inputObservable.subscribe((text) => { console.log('Texte saisie : ', text); }); ``` Dans cet exemple, nous utilisons la fonction fromEvent de RxJS pour créer un Observable à partir de l'événement d'entrée ('input') dans un champ de texte. Nous sélectionnons le champ de texte à l'aide de la méthode getElementById en lui passant l'identifiant 'myInput'. Ensuite, nous passons le champ de texte et le nom de l'événement 'input' à la fonction fromEvent. Cela crée un Observable qui émettra une valeur chaque fois que l'utilisateur saisit du texte dans le champ de texte. Nous utilisons ensuite les opérateurs map et debounceTime pour effectuer des transformations et des contrôles sur les valeurs émises par l'Observable. L'opérateur map est utilisé pour extraire la valeur de l'événement input, tandis que l'opérateur debounceTime est utilisé pour délaisser l'émission des valeurs pendant 300 millisecondes après chaque événement. Cela permet d'éviter des émissions trop fréquentes et de traiter uniquement la valeur après une pause dans la saisie. Enfin, nous nous abonnons à cet Observable transformé en utilisant la méthode subscribe et en fournissant une fonction callback qui sera exécutée chaque fois qu'un événement de saisie de texte se produit. Dans cet exemple, nous affichons simplement le texte saisi dans la console. Ainsi, chaque fois que l'utilisateur saisit du texte dans le champ de texte, le texte saisi sera affiché dans la console après une pause de 300 millisecondes depuis la dernière saisie. Ce sont là quelques exemples pratiques d'utilisation de RxJS pour la gestion des événements. Vous pouvez combiner différents opérateurs RxJS pour effectuer des opérations plus avancées, telles que la validation des données, la mise en cache des résultats, etc., en fonction de vos besoins spécifiques. > _Pour Info : L'opérateur debounceTime de RxJS est utilisé pour retarder l'émission des valeurs de l'Observable pendant une période spécifiée après chaque valeur émise. Cela permet de contrôler la fréquence d'émission des valeurs et de réagir uniquement aux valeurs finales après une période de calme._ > > _Lorsque vous appliquez l'opérateur debounceTime à un Observable, il commence à mesurer le temps écoulé après chaque valeur émise. Si aucune autre valeur n'est émise pendant la période spécifiée (en millisecondes), l'opérateur debounceTime émet la valeur actuelle. Si une nouvelle valeur est émise pendant la période de calme, le chronomètre est réinitialisé et le processus recommence._ > > _L'opérateur debounceTime est utile dans de nombreux cas, par exemple pour réduire la fréquence d'appels de requêtes à un serveur lors de la saisie d'un terme de recherche, ou pour réagir uniquement aux événements après une certaine période de calme pour éviter des traitements excessifs ou inutiles._ ## 4.2. Appels HTTP ### 4.2.1. Exemple de requête HTTP avec RxJS Voici un exemple pratique d'utilisation de RxJS avec HttpClient dans Angular pour effectuer une requête HTTP : ```typescript import { HttpClient } from '@angular/common/http'; // ... constructor(private http: HttpClient) {} // ... const url = 'https://api.example.com/data'; this.http.get(url).subscribe((response) => { console.log('Réponse de la requête HTTP : ', response); }, (error) => { console.log('Erreur de la requête HTTP : ', error); }); ``` Dans cet exemple, nous utilisons le service HttpClient fourni par Angular pour effectuer une requête HTTP GET vers l'URL spécifiée. HttpClient est un service intégré à Angular qui facilite l'envoi de requêtes HTTP et la gestion des réponses. Dans le constructeur de la classe (ou dans un autre endroit approprié), nous injectons HttpClient en tant que dépendance. Ensuite, nous utilisons la méthode get de HttpClient en passant l'URL cible pour effectuer la requête HTTP GET. L'observable retourné par la méthode get peut être souscrit avec la méthode subscribe. Dans la fonction de rappel du succès, nous recevons la réponse de la requête HTTP, que nous affichons dans la console. Si une erreur se produit lors de la requête, nous recevons l'erreur dans la fonction de rappel d'erreur, que nous affichons également dans la console. Il est important de noter que pour utiliser HttpClient, vous devez importer le module HttpClientModule dans votre module Angular et l'ajouter à la liste des imports. Cet exemple utilise la méthode GET pour effectuer une requête HTTP, mais vous pouvez également utiliser les méthodes POST, PUT, DELETE, etc., en utilisant les méthodes correspondantes de HttpClient (par exemple post, put, delete, etc.). L'utilisation de RxJS avec HttpClient dans Angular vous permet de gérer les requêtes HTTP de manière asynchrone, de réagir aux réponses, aux erreurs et de traiter les données de manière efficace et flexible. ### 4.2.2. Transformation des réponses Voici un exemple pratique d'utilisation de RxJS avec HttpClient dans Angular pour effectuer une requête HTTP et effectuer une transformation des réponses : ```typescript import { HttpClient } from '@angular/common/http'; import { map } from 'rxjs/operators'; // ... constructor(private http: HttpClient) {} // ... this.http.get(url).pipe( map((response) => { // Effectuer une transformation des données de la réponse ici return response; }) ).subscribe((transformedResponse) => { console.log('Données de la requête HTTP transformée : ', transformedResponse); }, (error) => { console.log('Erreur de la requête HTTP : ', error); }); ``` Dans cet exemple, nous utilisons le service HttpClient fourni par Angular pour effectuer une requête HTTP GET vers l'URL spécifiée. Nous utilisons également l'opérateur map de RxJS pour effectuer une transformation des données de la réponse. Dans le constructeur de la classe (ou dans un autre endroit approprié), nous injectons HttpClient en tant que dépendance. Ensuite, nous utilisons la méthode get de HttpClient en passant l'URL cible pour effectuer la requête HTTP GET. L'observable retourné par la méthode get peut être transformé en utilisant l'opérateur pipe et l'opérateur map. Dans l'opérateur map, vous pouvez effectuer une transformation des données de la réponse selon vos besoins. Vous pouvez modifier la structure des données, filtrer des éléments, effectuer des calculs, etc. Dans l'exemple, nous retournons simplement la réponse d'origine sans aucune transformation, mais vous pouvez ajouter votre propre logique ici. Ensuite, nous nous abonnons à l'Observable transformé en utilisant la méthode subscribe. Dans la fonction de rappel du succès, nous recevons la réponse transformée de la requête HTTP, que nous affichons dans la console. Si une erreur se produit lors de la requête, nous recevons l'erreur dans la fonction de rappel d'erreur, que nous affichons également dans la console. L'utilisation de RxJS avec HttpClient dans Angular vous permet de gérer les requêtes HTTP de manière asynchrone, d'effectuer des transformations des données, de réagir aux réponses et aux erreurs, et de traiter les données de manière efficace et flexible. # 5. Avantages et inconvénients de RxJS RxJS présente plusieurs avantages et inconvénients. Voici une liste des principaux : ## 5.1. Avantages de RxJS - Programmation réactive : RxJS permet de programmer de manière réactive en utilisant des Observables et des opérateurs, ce qui simplifie la gestion des flux de données asynchrones et des événements. - Composition et transformation des données : RxJS offre un large éventail d'opérateurs qui permettent de composer, transformer et filtrer facilement les flux de données. Cela facilite la manipulation des données et la réalisation de tâches complexes avec peu de code. - Gestion de la concurrence : Les Observables de RxJS peuvent gérer efficacement la concurrence en combinant, synchronisant et annulant les flux de données asynchrones. Cela facilite la coordination des opérations asynchrones complexes. - Gestion des erreurs : RxJS propose des opérateurs pour la gestion des erreurs, tels que catchError et retry, qui simplifient la gestion des erreurs dans les flux de données. - Prise en charge de la programmation réactive côté client et côté serveur : RxJS peut être utilisé à la fois côté client (dans les navigateurs) et côté serveur (dans des environnements tels que Node.js) pour une programmation réactive cohérente et efficace. ## 5.2. Inconvénients de RxJS - Courbe d'apprentissage : RxJS peut avoir une courbe d'apprentissage abrupte pour les développeurs qui ne sont pas familiers avec la programmation réactive et les concepts des Observables. Il peut nécessiter du temps pour maîtriser pleinement les concepts et les opérateurs de RxJS. - Complexité excessive pour les cas simples : Dans certains cas simples où la gestion des événements ou des flux de données est simple, l'utilisation de RxJS peut introduire une complexité inutile. L'ajout de RxJS peut être excessif pour des tâches simples et basiques. - Surcharge de taille : L'introduction de RxJS peut augmenter la taille du bundle JavaScript, car la bibliothèque RxJS elle-même est relativement volumineuse. Cela peut être préoccupant en particulier pour les applications à faible bande passante ou les applications où la taille du bundle est critique. Il est important de noter que les avantages et inconvénients de RxJS peuvent varier en fonction du cas d'utilisation spécifique et des compétences des développeurs. Dans certains cas, RxJS peut apporter de nombreux avantages, tandis que dans d'autres cas, son utilisation peut être moins appropriée. Il est important de considérer attentivement les avantages et les inconvénients avant de décider d'utiliser RxJS dans un projet donné. # 6. Conclusion Je vous encourage à explorer d’avantage RxJS. Quelques liens utiles : - https://rxjs.dev/ - https://www.learnrxjs.io/ - https://angular.io/ - https://angular.io/guide/rx-library # 7. Lexique ## 7.1. Paradigme de programmation Un paradigme de programmation est une approche ou un modèle conceptuel qui définit la manière dont les programmes informatiques sont structurés, conçus et exécutés. Il s'agit d'un ensemble de principes et de conventions qui guident les développeurs dans la résolution de problèmes et l'écriture de code. Il existe plusieurs paradigmes de programmation, chacun avec ses propres caractéristiques et techniques. Voici quelques-uns des paradigmes de programmation les plus courants : 1. Programmation impérative : Dans ce paradigme, le programme est structuré autour de séquences d'instructions qui modifient l'état du programme. Les langages comme le C et le Pascal suivent ce paradigme. 2. Programmation orientée objet : Ce paradigme se concentre sur la modélisation des concepts du monde réel sous forme d'objets. Les objets sont des instances de classes, qui regroupent des données et des méthodes associées. Java et C++ sont des exemples de langages orientés objet. 3. Programmation fonctionnelle : Ce paradigme met l'accent sur l'évaluation de fonctions mathématiques pures, sans état mutable ni effets de bord. Les langages comme Haskell et Lisp suivent ce paradigme. 4. Programmation logique : Dans ce paradigme, le programme est construit en décrivant les relations logiques entre les faits et les règles. Prolog est un langage couramment utilisé pour la programmation logique. 5. Programmation structurée : Ce paradigme encourage l'utilisation de structures de contrôle telles que les boucles et les instructions conditionnelles pour organiser le code de manière claire et compréhensible. C et Pascal sont souvent cités comme des langages de programmation structurée. Il est important de noter que certains langages de programmation peuvent prendre en charge plusieurs paradigmes. Par exemple, des langages comme Python et JavaScript peuvent être utilisés de manière impérative, orientée objet et fonctionnelle, offrant ainsi une plus grande flexibilité aux développeurs. Le choix du paradigme dépend souvent des besoins du projet, de la complexité du problème à résoudre et des préférences du développeur. ## 7.2. Lazy En programmation, le terme "lazy" (paresseux en français) fait référence à une technique d'évaluation différée ou d'évaluation à la demande. L'idée principale est de retarder l'évaluation d'une expression ou d'un calcul jusqu'à ce que cela soit absolument nécessaire. Le Lazy permet de gagner en efficacité en évitant d'effectuer des calculs inutiles. Plutôt que d'évaluer une expression immédiatement, elle est évaluée uniquement lorsque le résultat est réellement requis. Le Lazy peut être un outil puissant pour optimiser les performances et économiser des ressources dans certains cas, mais elle nécessite une compréhension précise de la sémantique d'évaluation du langage utilisé. Dans certains cas, elle peut également entraîner des comportements inattendus si elle n'est pas utilisée correctement.