Мое обходное решение:
function add(a, b, precision) {
var x = Math.pow(10, precision || 2);
return (Math.round(a * x) + Math.round(b * x)) / x;
}
precision относится к числу цифр, которые вы хотите сохранить после десятичной точки во время добавления.
A Subject
или Observable
не имеет текущего значения. Когда значение испускается, оно передается подписчикам, а Observable
выполняется с ним.
Если вы хотите иметь текущее значение, используйте BehaviorSubject
, который предназначен именно для этой цели. BehaviorSubject
сохраняет последнее испущенное значение и немедленно отправляет его новым подписчикам.
Он также имеет метод getValue()
для получения текущего значения.
Если вы используете 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()
, чтобы подписаться на источник с объектом. У меня была схожая ситуация, когда поздние подписчики подписывались на Субъект после того, как его значение прибыло.
Я нашел ReplaySubject , который похож на BehaviorSubject, работает как шарм в этом случае. И вот ссылка на лучшее объяснение: http://reactivex.io/rxjs/manual/overview.html#replaysubject
Я столкнулся с той же проблемой в дочерних компонентах, где изначально она должна была иметь текущее значение Субъекта, а затем подписаться на Субъект для прослушивания изменений. Я просто поддерживаю текущее значение в Сервисе, поэтому оно доступно для доступа к компонентам, например. :
import {Storage} from './storage';
import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class SessionStorage extends Storage {
isLoggedIn: boolean;
private _isLoggedInSource = new Subject<boolean>();
isLoggedIn = this._isLoggedInSource.asObservable();
constructor() {
super('session');
this.currIsLoggedIn = false;
}
setIsLoggedIn(value: boolean) {
this.setItem('_isLoggedIn', value, () => {
this._isLoggedInSource.next(value);
});
this.isLoggedIn = value;
}
}
Компонент, который нуждается в текущем значении, может просто получить к нему доступ из службы, то есть:
sessionStorage.isLoggedIn
Не уверен, что это правильная практика :)
Вы можете сохранить последнее испущенное значение отдельно от наблюдаемого. Затем прочитайте его, когда это необходимо.
let lastValue: number;
const subscription = new Service().start();
subscription
.subscribe((data) => {
lastValue = data;
}
);