我有一个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的当前值。我该怎么做呢?


当前回答

我在子组件中遇到了同样的问题,最初它必须拥有Subject的当前值,然后订阅Subject以侦听更改。我只是在服务中维护当前值,以便组件可以访问它,例如:

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

不确定这是否是正确的做法:)

其他回答

最好的方法是使用行为主语,下面是一个例子:

var sub = new rxjs.BehaviorSubject([0, 1])
sub.next([2, 3])
setTimeout(() => {sub.next([4, 5])}, 1500)
sub.subscribe(a => console.log(a)) //2, 3 (current value) -> wait 2 sec -> 4, 5
const observable = of('response')

function hasValue(value: any) {
  return value !== null && value !== undefined;
}

function getValue<T>(observable: Observable<T>): Promise<T> {
  return observable
    .pipe(
      filter(hasValue),
      first()
    )
    .toPromise();
}

const result = await getValue(observable)
// Do the logic with the result
// .................
// .................
// .................

您可以从这里查看关于如何实现它的完整文章。 https://www.imkrish.com/blog/development/simple-way-get-value-from-observable

唯一的方法,你应该得到值“出”一个可观察对象/主题是与订阅!

如果你在使用getValue()你在做一些声明式的命令。它是一个逃生口,但是99.9%的情况下你不应该使用getValue()。getValue()会做一些有趣的事情:如果主题已经取消订阅,它会抛出一个错误,如果主题已经死亡,它会阻止你获得一个值,因为它是错误的,等等。但是,再一次地,它是在罕见情况下的一个逃生口。

有几种方法可以以“Rx-y”方式从Subject或Observable中获取最新的值:

Using BehaviorSubject: But actually subscribing to it. When you first subscribe to BehaviorSubject it will synchronously send the previous value it received or was initialized with. Using a ReplaySubject(N): This will cache N values and replay them to new subscribers. A.withLatestFrom(B): Use this operator to get the most recent value from observable B when observable A emits. Will give you both values in an array [a, b]. A.combineLatest(B): Use this operator to get the most recent values from A and B every time either A or B emits. Will give you both values in an array. shareReplay(): Makes an Observable multicast through a ReplaySubject, but allows you to retry the observable on error. (Basically it gives you that promise-y caching behavior). publishReplay(), publishBehavior(initialValue), multicast(subject: BehaviorSubject | ReplaySubject), etc: Other operators that leverage BehaviorSubject and ReplaySubject. Different flavors of the same thing, they basically multicast the source observable by funneling all notifications through a subject. You need to call connect() to subscribe to the source with the subject.

Subject或Observable没有当前值。当一个值被触发时,它被传递给订阅者,Observable就完成了对它的处理。

如果你想要一个当前值,请使用专门为此目的设计的BehaviorSubject。BehaviorSubject保留最后发出的值,并立即将其发出给新的订阅者。

它还有一个getValue()方法来获取当前值。

我在子组件中遇到了同样的问题,最初它必须拥有Subject的当前值,然后订阅Subject以侦听更改。我只是在服务中维护当前值,以便组件可以访问它,例如:

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

不确定这是否是正确的做法:)