Как поделиться одним источником - PullRequest
0 голосов
/ 25 июня 2019

Я пытаюсь разделить источник Subject для нескольких функций, которые фильтруют их действия и выполняют соответствующие задачи, а те, которые не отфильтрованы, должны упасть без изменений.

Я пытался объединить один и тот же источник, но он не работает так, как мне нужно ...

const source = new Subject()

source.next({ type: 'some type', action: {} })

merge(
  source,
  source.pipe(filter(...), do something),
  source.pipe(filter(...), do something),
  source.pipe(filter(...), do something),
  source.pipe(filter(...), do something),
).subscribe(...)

В этом случае я получаю исходный источник + отфильтрованные.

Я ожидаю, что смогу предоставить один и тот же источник нескольким функциям, которые могут фильтровать по типам и выполнять асинхронное поведение, остальные типы, которые не были отфильтрованы, должны упасть.Надеюсь, что это достаточно ясно, или иначе постараемся сделать лучший пример.Спасибо!

пример здесь

1 Ответ

0 голосов
/ 25 июня 2019

В основном вам нужен один источник с действиями. Тема - хороший способ сделать это.

Затем вы хотите выполнить некоторую обработку для каждого типа действия. Вы можете filter и subscribe для каждого подпотока.

const add$ = source.pipe(filter(a => a.type === "add")).subscribe(function onAddAction(a) {});
const remove$ = source.pipe(filter(a => a.type === "remove")).subscribe(function onRemove(a) {});

Или вы можете подготовить подпотоки, а затем снова объединить их со всеми обработанными действиями.

const add$ = source.pipe(filter(a => a.type === "add"), tap(onAdd));
const remove$ = source.pipe(filter(a => a.type === "remove"), tap(onRemove));
const processedAction$ = merge(add$, remove$);
processedAction$.subscribe(logAction);

Если вам нужно выполнить некоторую предварительную обработку всех действий, вы можете использовать share или shareReplay. toAction будет вызываться только один раз за каждый элемент.

const subject = new Subject();
const action$ = subject.pipe(map(toAction), share());
const add$ = action$.pipe(filter(isAdd));
...
merge(add$, remove$).subscribe(logAction);

А если у вас проблемы с разбиением:

function not(predicate) {
    return function(item, ...args) {
        return !predicate(item, ...args);
    }

}

function any(...predicates) {
    return function(item, ...args) {
         return predicates.some(p => p(item, ...args));
    }
}

const a = source.pipe(filter(fa), map(doA));
const b = source.pipe(filter(fb), map(doB));
const c = source.pipe(filter(fc), map(doC));
const rest = source.pipe(filter(not(any(fa, fb, fc)));
merge(a, b, c, rest).subscribe(logAction);
...