web-dev-qa-db-fra.com

Diviser Rx Observable en plusieurs flux et traiter individuellement

Voici une image de ce que je tente d'accomplir.

--a-b-c-a - bbb - a

divisé en

--a ----- a ------- a -> un flux

---- b ------ bbb --- -> b flux

------ c ---------- -> c stream

Ensuite, pouvoir

a.subscribe()
b.subscribe()
c.subscribe()

Jusqu'à présent, tout ce que j'ai trouvé a divisé le flux à l'aide d'un groupBy (), puis tout réduit en un seul flux et les a tous traités dans la même fonction. Ce que je veux faire, c'est traiter chaque flux dérivé de manière différente.

Ce que je fais actuellement, c'est un tas de filtres. Y a-t-il une meilleure manière de faire cela?

30
Brandon Bil

Vous n'êtes pas obligé de réduire Observables de groupBy. Vous pouvez plutôt vous y abonner.

Quelque chose comme ça:

    String[] inputs= {"a", "b", "c", "a", "b", "b", "b", "a"};

    Action1<String> a = s -> System.out.print("-a-");

    Action1<String> b = s -> System.out.print("-b-");

    Action1<String> c = s -> System.out.print("-c-");

    Observable
            .from(inputs)
            .groupBy(s -> s)
            .subscribe((g) -> {
                if ("a".equals(g.getKey())) {
                    g.subscribe(a);
                }

                if ("b".equals(g.getKey())) {
                    g.subscribe(b);
                }

                if ("c".equals(g.getKey())) {
                    g.subscribe(c);
                }
            });

Si les déclarations semblent un peu moche mais au moins, vous pouvez gérer chaque flux séparément. Peut-être qu'il y a un moyen de les éviter.

13
ihuk

Facile comme bonjour, utilisez simplement filter

Un exemple en scala

import rx.lang.scala.Observable

val o: Observable[String] = Observable.just("a", "b", "c", "a", "b", "b", "b", "a")
val hotO: Observable[String] = o.share
val aSource: Observable[String] = hotO.filter(x ⇒ x == "a")
val bSource: Observable[String] = hotO.filter(x ⇒ x == "b")
val cSource: Observable[String] = hotO.filter(x ⇒ x == "c")

aSource.subscribe(o ⇒ println("A: " + o), println, () ⇒ println("A Completed"))

bSource.subscribe(o ⇒ println("B: " + o), println, () ⇒ println("B Completed"))

cSource.subscribe(o ⇒ println("C: " + o), println, () ⇒ println("C Completed"))

Vous devez juste vous assurer que la source observable est chaude. Le moyen le plus simple consiste à share le.

36
Tomáš Dvořák

Votre question porte la mention rx-Java et rxjs. J'ai donc pensé poster une réponse pour rxjs.

J'ai eu le même problème et utilisé partition pour résoudre le problème. Voici essentiellement ce que j'ai fait:

import { from } from 'rxjs';
import { partition } from 'rxjs/operators';

const source = from([{category: 1, value: 10}, {category: 2, value: 20}]);

const categories = source.pipe(partition(v => v.category));
for (c of categories) {
    c.pipe(
        // etc
    ).subscribe(val => {
        // etc
    });
}

NOTE: je n'ai pas testé cet exemple. Si vous rencontrez des problèmes, éditez le message. Merci!

J'ai paraphrasé cet exemple dans la documentation officielle: https://www.learnrxjs.io/operators/transformation/partition.html

0
James Watkins