La semaine dernière, j'ai répondu à une question RxJS où j'ai eu une discussion avec un autre membre de la communauté sur: "Dois-je créer un abonnement pour chaque effet secondaire spécifique ou dois-je essayer de minimiser les abonnements en général?" Je veux savoir quelle méthologie utiliser en termes d'approche applicative réactive complète ou quand passer de l'un à l'autre. Cela m'aidera et peut-être d'autres à éviter les discussions sans crainte.
Informations de configuration
- Tous les exemples sont en TypeScript
- Pour mieux se concentrer sur la question, pas d'utilisation des cycles de vie / constructeurs pour les abonnements et pour garder le cadre sans rapport
- Imaginez: les abonnements sont ajoutés dans constructeur / cycle de vie init
- Imaginez: la désinscription se fait dans le cycle de vie détruire
Qu'est-ce qu'un effet secondaire (échantillon angulaire)
- Mise à jour / entrée dans l'interface utilisateur (par exemple
value$ | async
) - Sortie / amont d'un composant (par exemple
@Output event = event$
) - Interaction entre différents services sur différentes hiérarchies
Cas d'utilisation exemplaire:
- Deux fonctions:
foo: () => void; bar: (arg: any) => void
- Deux sources observables:
http$: Observable<any>; click$: Observable<void>
foo
est appelé aprèshttp$
avoir émis et n'a besoin d'aucune valeurbar
est appelé après l'click$
émission, mais a besoin de la valeur actuelle dehttp$
Cas: Créez un abonnement pour chaque effet secondaire spécifique
const foo$ = http$.pipe(
mapTo(void 0)
);
const bar$ = http$.pipe(
switchMap(httpValue => click$.pipe(
mapTo(httpValue)
)
);
foo$.subscribe(foo);
bar$.subscribe(bar);
Cas: minimiser les abonnements en général
http$.pipe(
tap(() => foo()),
switchMap(httpValue => click$.pipe(
mapTo(httpValue )
)
).subscribe(bar);
Ma propre opinion en bref
Je peux comprendre le fait que les abonnements rendent les paysages Rx plus complexes au début, car vous devez penser à la façon dont les abonnés devraient affecter la pipe ou non par exemple (partagez votre observable ou non). Mais plus vous séparez votre code (plus vous vous concentrez: que se passe-t-il quand), plus il est facile de maintenir (tester, déboguer, mettre à jour) votre code à l'avenir. Dans cet esprit, je crée toujours une seule source observable et un seul abonnement pour tout effet secondaire dans mon code. Si deux ou plusieurs effets secondaires que j'ai sont déclenchés par la même source observable, je partage mon observable et je souscris à chaque effet secondaire individuellement, car il peut avoir des cycles de vie différents.
la source
takeUntil
associée à une fonction appelée depuisngOnDestroy
. Il est une doublure qui l' ajoute à la conduite:takeUntil(componentDestroyed(this))
. stackoverflow.com/a/60223749/5367916si l'optimisation des abonnements est votre fin de partie, pourquoi ne pas aller à l'extrême logique et suivre simplement ce schéma général:
L'exécution exclusive des effets secondaires dans le robinet et l'activation avec la fusion signifie que vous n'avez qu'un seul abonnement.
Une raison de ne pas le faire est que vous neutralisez une grande partie de ce qui rend RxJS utile. Il s'agit de la possibilité de composer des flux observables et de vous abonner / vous désabonner des flux selon les besoins.
Je dirais que vos observables devraient être logiquement composés, et non pollués ou confondus au nom de la réduction des abonnements. L'effet foo doit-il logiquement être couplé à l'effet bar? L'un nécessite-t-il l'autre? Pourrai-je jamais ne pas vouloir déclencher foo lorsque http $ émet? Suis-je en train de créer un couplage inutile entre des fonctions indépendantes? Ce sont toutes des raisons pour éviter de les mettre dans un seul flux.
Tout cela ne prend même pas en compte la gestion des erreurs qui est plus facile à gérer avec plusieurs abonnements IMO
la source