На прошлой неделе я ответил на вопрос RxJS, где я вступил в дискуссию с другим членом сообщества на тему : «Должен ли я создать подписку для каждого конкретного побочного эффекта или я должен попытаться минимизировать подписки в целом?» Я хочу знать, какую методологию использовать с точки зрения полного реактивного подхода к применению или когда переключаться с одного на другой. Это поможет мне и, возможно, другим избежать ненужных дискуссий.
Информация о настройке
- Все примеры в TypeScript
- Чтобы лучше сосредоточиться на вопросе, не использовать жизненные циклы / конструкторы для подписок и держать в рамках не связанными
- Представьте себе: подписки добавляются в init конструктора / жизненного цикла
- Представьте себе: отмена подписки осуществляется в жизненном цикле уничтожения
Что такое побочный эффект (угловой образец)
- Обновление / ввод в пользовательском интерфейсе (например
value$ | async
) - Выход / восходящий поток компонента (например
@Output event = event$
) - Взаимодействие между различными службами в разных иерархиях
Примерный вариант использования:
- Две функции:
foo: () => void; bar: (arg: any) => void
- Две исходные наблюдаемые:
http$: Observable<any>; click$: Observable<void>
foo
вызывается после того, какhttp$
выпустил и не нуждается в значенииbar
вызывается послеclick$
эмиссии, но нуждается в текущем значенииhttp$
Случай: создать подписку для каждого конкретного побочного эффекта
const foo$ = http$.pipe(
mapTo(void 0)
);
const bar$ = http$.pipe(
switchMap(httpValue => click$.pipe(
mapTo(httpValue)
)
);
foo$.subscribe(foo);
bar$.subscribe(bar);
Дело: Минимизировать подписки в целом
http$.pipe(
tap(() => foo()),
switchMap(httpValue => click$.pipe(
mapTo(httpValue )
)
).subscribe(bar);
Мое собственное мнение вкратце
Я могу понять тот факт, что подписки вначале усложняют Rx-ландшафты, потому что вы должны думать о том, как подписчики, например, должны влиять на канал или нет (поделиться своими наблюдаемыми или нет). Но чем больше вы разделяете свой код (чем больше вы сосредотачиваетесь: что происходит, когда), тем легче поддерживать (тестировать, отлаживать, обновлять) ваш код в будущем. Имея это в виду, я всегда создаю один наблюдаемый источник и одну подписку для любого побочного эффекта в моем коде. Если два или более моих побочных эффектов вызваны одним и тем же наблюдаемым источником, то я делюсь своим наблюдаемым и подписываюсь на каждый побочный эффект индивидуально, потому что он может иметь разные жизненные циклы.
источник
takeUntil
в сочетании с функцией, которая вызывается изngOnDestroy
. Это один лайнер , который добавляет это к трубе:takeUntil(componentDestroyed(this))
. stackoverflow.com/a/60223749/5367916если оптимизация подписок - это ваша конечная игра, почему бы не пойти до логического предела и просто следовать этой общей схеме:
Исключительное выполнение побочных эффектов при нажатии и активация с помощью слияния означает, что у вас только одна подписка.
Одна из причин не делать этого состоит в том, что вы кастрируете большую часть того, что делает RxJS полезным. Который является способностью составлять наблюдаемые потоки и подписываться / отписываться от потоков по мере необходимости.
Я бы сказал, что ваши наблюдаемые должны быть логически составлены, а не загрязнены или запутаны во имя сокращения подписок. Должен ли эффект foo логически сочетаться с эффектом бара? Нужно ли одно другому? Могу ли я когда-нибудь не захотеть запускать foo, когда http $ выбрасывает? Я создаю ненужную связь между несвязанными функциями? Это все причины, чтобы не помещать их в один поток.
Это все даже не учитывая обработку ошибок, которой проще управлять с помощью нескольких подписок IMO
источник