#angular #rxjs #behaviorsubject
#angular #rxjs #behaviorsubject
Вопрос:
У меня есть следующий код:
class MyClass {
private readonly clientId$: ReplaySubject<string>;
public get clientId(): Observable<string> {
return this.clientId$;
}
constructor([... things]) {
this.clientId$ = new ReplaySubject<string>(1);
someObservable
.pipe(
map(arg => {
// business logic and what not...
}))
.subscribe(clientId => {
this.clientId$.next(clientId);
});
}
}
Я хочу иметь возможность использовать myClassInstance.clientId.value();
, например, как объект поведения. В дополнение к новым подписчикам clientId
, получающим старое значение, поскольку someObservable
оно срабатывает нечасто.
Есть идеи? Заранее благодарю вас!
Комментарии:
1. зачем вам это нужно? размер вашего буфера равен 1 для replaysubject, что существенно делает его похожим на BehaviourSubject.
2. Я хотел бы иметь возможность использовать его вне rxjs, как простое значение.
3. не можете ли вы иметь другую переменную класса и назначить последнее значение в блоке подписки, где вы отправляете идентификатор клиента?
4. Синхронный геттер в
BehaviorSubject
любомclientId.value
илиclientId.getValue()
нетclientId.value()
. И это доступно только вBehaviorSubject
. Если вам это нужно, вы можете использовать значение по умолчаниюnull
дляBehaviorSubject
и не использовать его в подписке.5. Это то, что
BehaviorSubject
делает a . Если вы подписываетесь на aBehaviorSubject
, вы получаете его текущее (т. Е. Последнее) значение.
Ответ №1:
Хотя это не дает прямого ответа на ваш вопрос, я хотел бы отметить, что вам, вероятно, вообще не нужен subject!
Подписка на observable, просто для того, чтобы передать значение в свой собственный объект, обычно не требуется.
В вашем случае вам не нужен ReplaySubject, вам не нужен геттер, и вам не нужно подписываться в вашем конструкторе.
Это должно выполнить эту работу:
class MyClass {
constructor(private someService:SomeService) { }
clientId$ = this.someService.someObservable.pipe(
map(val => val.clientId)
);
}
Что касается доступа к последнему значению… вы могли бы спрятать его в локальной переменной:
clientId$ = this.someService.someObservable.pipe(
map(val => val.clientId),
tap(clientId => this.clientId = clientId)
);
Но часто в этом тоже нет необходимости. Если вы используете async
канал в своем шаблоне, вы уже получаете развернутое последнее значение.
<h3 *ngIf="clientId$ | async as clientId">{{ clientId }}</h3>
Комментарии:
1. Есть тонкое, но важное отличие: проходя через многоадресную рассылку источника, ваш способ этого не делает. Если источник дорогой или не идемпотентный, как сетевой запрос, это становится большой проблемой. Конечно, многоадресная рассылка может быть достигнута с помощью операторов, которые скрывают объект, но все же используют объект.
2. Я также не уверен, какая часть вопроса заставляет вас сказать, что OP не нуждается в воспроизведении идентификатора клиента. Для этого есть много веских причин, нет информации о том, что они хотят делать, и нет информации о том, уже воспроизведен источник или нет.
3. И, наконец, ваш ответ пропускает различия в обработке ошибок по сравнению с исходным решением, что также может сыграть важную роль. В целом намерение здесь хорошее, но ответ недостаточно детализирован, чтобы слепо рекомендовать не использовать subject .
4. Спасибо, что указали на эти различия. Вы правы, важно знать о проблемах с множественным воспроизведением и обработкой ошибок и
share
при необходимости использоватьshareReplay
операторы or. Мое намерение состояло не в том, чтобы вообще избегать использования subjects, а в том, чтобы указать на то, что, я думаю, не очевидно для многих новичков rxjs, а именно: вам не нужно использовать Subject для ввода значений «вручную» через поток. Часто гораздо проще преобразовать существующий наблюдаемый поток в нужную вам форму.5. Я согласен, и особенно с тем фактом, что новички слишком часто прибегают к этому, поэтому я говорю, что намерение здесь хорошее (и во многом я согласен с вами). Мои комментарии не совсем глубокое погружение в эти вопросы, но я надеюсь, что они добавляют некоторый контекст к ответу, который кто-то должен рассмотреть. Приветствия.