У меня есть сервис Angular 2:
import {Storage} from './storage';
import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class SessionStorage extends Storage {
private _isLoggedInSource = new Subject<boolean>();
isLoggedIn = this._isLoggedInSource.asObservable();
constructor() {
super('session');
}
setIsLoggedIn(value: boolean) {
this.setItem('_isLoggedIn', value, () => {
this._isLoggedInSource.next(value);
});
}
}
Все отлично работает. Но у меня есть другой компонент, которому не нужно подписываться, ему просто нужно получить текущее значение isLoggedIn в определенный момент времени. Как я могу это сделать?
javascript
angular
rxjs
Baconbeastnz
источник
источник
getValue()
красного флага - вы делаете что-то не так. Это как спасательный люк. Обычно все, что вы делаете с RxJS, должно быть декларативным.getValue()
обязательно. Если вы используетеgetValue()
, есть вероятность 99,9%, что вы делаете что-то не так или странно.BehaviorSubject<boolean>(false)
и нравится переключать его?foo$
былоBehaviorSubject
(то есть оно определено как,Observable
а может, горячее или холодное из отложенного источника). Однако , так как вы затем перейти к использованию.next
на$foo
себе , что означает , что ваша реализация зависит от него бытьBehaviorSubject
так что нет никаких оснований для не только с помощью ,.value
чтобы получить текущее значение в первую очередь.Единственный способ, которым вы должны получать значения «из» Observable / Subject - это подписаться!
Если вы используете,
getValue()
вы делаете что-то обязательное в декларативной парадигме. Он есть в качестве аварийного люка, но 99,9% времени НЕ следует использоватьgetValue()
. Есть несколько интересных вещей, которыеgetValue()
будут делать: он выдаст ошибку, если субъект был отписан, он не даст вам получить значение, если субъект мертв, потому что он ошибочен, и т. Д. Но, опять же, это как выход люк для редких обстоятельств.Есть несколько способов получить последнее значение от субъекта или наблюдаемого способом «Rx-y»:
BehaviorSubject
: Но на самом деле подписаться на это . Когда вы впервые подписываетесь наBehaviorSubject
него, он будет синхронно отправлять предыдущее значение, которое он получил или был инициализирован.ReplaySubject(N)
: Это кешируетN
значения и воспроизводит их новым подписчикам.A.withLatestFrom(B)
: Используйте этот оператор, чтобы получить самое последнее значение из наблюдаемого,B
когда наблюдаемоеA
излучает. Даст вам оба значения в массиве[a, b]
.A.combineLatest(B)
: Используйте этот оператор , чтобы получить самые последние значения отA
иB
каждый раз , когда либоA
илиB
испускает. Даст вам оба значения в массиве.shareReplay()
: Создает наблюдаемую многоадресную рассылку черезReplaySubject
, но позволяет вам повторить наблюдаемое при ошибке. (В основном это дает вам обещанное поведение кеширования).publishReplay()
,publishBehavior(initialValue)
,multicast(subject: BehaviorSubject | ReplaySubject)
И т.д.: Другие операторы , которые используютBehaviorSubject
иReplaySubject
. Различные разновидности одного и того же, они в основном направляют источник, наблюдаемый путем направления всех уведомлений через субъект. Вам нужно позвонить,connect()
чтобы подписаться на источник с темой.источник
click$.mergeMap(() => behaviorSubject.take(1))
решить свою проблему.AuthenticationService
который используетBehaviourSubject
для хранения текущего вошедшего в систему состояния (boolean
true
илиfalse
). Это предоставляетisLoggedIn$
обозримое для подписчиков, которые хотят знать, когда состояние меняется. Он также предоставляетget isLoggedIn()
свойство, которое возвращает текущее состояние входа в систему, вызываяgetValue()
базовый объектBehaviourSubject
- это используется моим средством проверки подлинности для проверки текущего состояния. Это кажется разумным использованиемgetValue()
для меня ...?У меня была похожая ситуация, когда поздние подписчики подписывались на Предмет после того, как его ценность прибыла.
Я обнаружил, что ReplaySubject, который похож на BehaviorSubject, в этом случае работает как шарм. А вот ссылка на лучшее объяснение: http://reactivex.io/rxjs/manual/overview.html#replaysubject
источник
next()
функция еще не была вызвана, в то время как BehaviourSubject делает. Немедленный выброс очень удобен для применения значений по умолчанию к представлению, когда BehaviourSubject используется в качестве источника данных, наблюдаемого в службе, напримерВы можете проверить полную статью о том, как реализовать это здесь. https://www.imkrish.com/how-to-get-current-value-of-observable-in-a-clean-way/
источник
Я сталкивался с той же проблемой в дочерних компонентах, где первоначально он должен иметь текущее значение Subject, а затем подписаться на Subject для прослушивания изменений. Я просто поддерживаю текущее значение в Сервисе, чтобы оно было доступно для компонентов, например:
Компонент, которому нужно текущее значение, может просто получить к нему доступ из службы, то есть:
Не уверен, что это правильная практика :)
источник
async
канал.Аналогичный ищет ответ был downvoted. Но я думаю, что могу оправдать то, что я предлагаю здесь для ограниченных случаев.
Хотя верно, что наблюдаемая не имеет текущего значения, очень часто она будет иметь сразу доступное значение. Например, в хранилищах redux / flux / akita вы можете запрашивать данные из центрального хранилища, основываясь на количестве наблюдаемых, и это значение обычно будет сразу же доступно.
Если это так, то когда вы
subscribe
, значение вернется немедленно.Допустим, у вас был вызов в службу, и по окончании вы хотите получить из своего магазина самую свежую ценность, которая потенциально может не генерироваться :
Вы можете попытаться сделать это (и вы должны как можно больше держать вещи «в трубах»):
Проблема в том, что он будет блокироваться до тех пор, пока вторичная наблюдаемая не выдаст значение, которое потенциально может никогда не быть.
В последнее время я обнаружил, что мне нужно оценивать наблюдаемое только в том случае, если значение было немедленно доступно , и, что более важно, мне нужно было уметь определять, не было ли оно. Я закончил тем, что сделал это:
Обратите внимание, что для всего вышеперечисленного я использую,
subscribe
чтобы получить значение (как обсуждает @Ben). Не используя.value
собственность, даже если бы у меня былBehaviorSubject
.источник
Хотя это может показаться излишним, но это просто еще одно «возможное» решение, позволяющее сохранить наблюдаемый тип и уменьшить шаблон…
Вы всегда можете создать расширение для получения текущего значения Observable.
Чтобы сделать это, вам нужно расширить
Observable<T>
интерфейс вglobal.d.ts
файле объявления типографий. Затем осуществить расширение геттер вobservable.extension.ts
файле и , наконец , включают в себя как типизации и файл расширения для вашего приложения.Вы можете обратиться к этому ответу StackOverflow, чтобы узнать, как включить расширения в ваше приложение Angular.
источник
Вы можете хранить последнее переданное значение отдельно от Observable. Тогда прочитайте это когда необходимо.
источник
Лучший способ сделать это с помощью
Behaviur Subject
, вот пример:источник
Подписка может быть создана и после получения первого испущенного элемента уничтожена. Труба - это функция, которая использует Observable в качестве входных данных и возвращает другой Observable в качестве выходных данных, не изменяя первую наблюдаемую. Угловой 8.1.0. Пакеты:
"rxjs": "6.5.3"
,"rxjs-observable": "0.0.7"
источник