如何获取RxJS Subject或Observable的当前值?

2020/10/13 23:01 · javascript ·  · 0评论

我有一个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的当前值即可。我怎样才能做到这一点?

一个SubjectObservable没有的电流值。发出值时,将其传递给订户并Observable使用它完成。

如果要使用当前值,请使用BehaviorSubject专门用于该目的的值。BehaviorSubject保留最后发出的值,并立即将其发送给新订户。

它还具有一种getValue()获取当前值的方法。

应该 从“可观察/对象”中获取值的唯一方法是订阅!

如果您使用的getValue()是声明式范例,则必须执行某些命令。它可以作为逃生舱口,但99.9%的时间不应该使用getValue()有一些有趣的事情getValue()可以做:如果主题已取消订阅,它将引发错误;如果主题因错误而死亡,则将阻止您获取值。等等。但是,再次出现是为了逃脱在极少数情况下孵化。

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

  1. 使用BehaviorSubject:但实际上是订阅它首次订阅时BehaviorSubject,它将同步发送它收到或初始化时使用的先前值。
  2. 使用ReplaySubject(N):这将缓存N值并将其重播给新订户。
  3. A.withLatestFrom(B):使用此运算符可以B在可观察到的A发射从可观察的获取最新值将在数组中同时提供两个值[a, b]
  4. A.combineLatest(B):使用该运营商从中获取最新的值AB每一次无论是AB发出。将在数组中同时提供两个值。
  5. shareReplay():通过进行可观察的多播ReplaySubject,但允许您在发生错误时重试可观察的。(基本上,它为您提供了promise-y缓存行为)。
  6. publishReplay()publishBehavior(initialValue)multicast(subject: BehaviorSubject | ReplaySubject),等:其它运营商,充分利用BehaviorSubjectReplaySubject相同事物具有不同的风格,它们基本上通过将所有通知集中到主题中来多播可观察的源。您需要致电connect()以订阅带有该主题的来源。

我也遇到过类似的情况,即后期订阅者在其价值到达后就订阅了该主题。

我发现ReplaySubject与BehaviorSubject相似,在这种情况下,它就像一个饰物。这是更好解释的链接:http : //reactivex.io/rxjs/manual/overview.html#replaysubject

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

我在子组件中遇到了相同的问题,最初它必须具有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

不知道这是否是正确的做法:)

类似的寻找答案downvoted。但是我认为我可以证明我在有限情况下的建议。


确实,可观察对象没有当前值,但通常情况下它将具有立即可用的值。例如,对于redux / flux / akita存储库,您可以根据多个可观察对象从中央存储库请求数据,并且通常可以立即获得该值。

如果是这种情况,那么当您输入时subscribe,该值将立即返回。

假设您有一个服务呼叫,完成后您想从商店中获取某物的最新价值,可能不会发出

您可以尝试执行此操作(并且应尽可能将内容保留在“管道内”):

 serviceCallResponse$.pipe(withLatestFrom(store$.select(x => x.customer)))
                     .subscribe(([ serviceCallResponse, customer] => {

                        // we have serviceCallResponse and customer 
                     });

问题在于它将阻塞直到辅助可观察对象发出一个值,该值可能永远不会出现。

我发现自己最近仅在值立即可用时才需要评估一个可观察,更重要的是,我需要能够检测它是否不可用。我最终这样做:

 serviceCallResponse$.pipe()
                     .subscribe(serviceCallResponse => {

                        // immediately try to subscribe to get the 'available' value
                        // note: immediately unsubscribe afterward to 'cancel' if needed
                        let customer = undefined;

                        // whatever the secondary observable is
                        const secondary$ = store$.select(x => x.customer);

                        // subscribe to it, and assign to closure scope
                        sub = secondary$.pipe(take(1)).subscribe(_customer => customer = _customer);
                        sub.unsubscribe();

                        // if there's a delay or customer isn't available the value won't have been set before we get here
                        if (customer === undefined) 
                        {
                           // handle, or ignore as needed
                           return throwError('Customer was not immediately available');
                        }
                     });

请注意,对于以上所有内容,我都在使用subscribe获取值(如@Ben讨论的那样)。.value即使使用,也不会使用属性BehaviorSubject

尽管这听起来有些矫kill过正,但这只是保持Observable类型并减少样板的另一种“可能”解决方案

您总是可以创建扩展获取器来获取Observable的当前值。

为此,您需要Observable<T>在类型global.d.ts声明文件中扩展接口然后文件中实现扩展名getterobservable.extension.ts最后将类型和扩展名文件都包括到您的应用程序中。

您可以参考此StackOverflow答案以了解如何将扩展包括在Angular应用程序中。

// global.d.ts
declare module 'rxjs' {
  interface Observable<T> {
    /**
     * _Extension Method_ - Returns current value of an Observable.
     * Value is retrieved using _first()_ operator to avoid the need to unsubscribe.
     */
    value: Observable<T>;
  }
}

// observable.extension.ts
Object.defineProperty(Observable.prototype, 'value', {
  get <T>(this: Observable<T>): Observable<T> {
    return this.pipe(
      filter(value => value !== null && value !== undefined),
      first());
  },
});

// using the extension getter example
this.myObservable$.value
  .subscribe(value => {
    // whatever code you need...
  });

您可以将上一个发出的值与Observable分开存储。然后在需要时阅读它。

let lastValue: number;

const subscription = new Service().start();
subscription
    .subscribe((data) => {
        lastValue = data;
    }
);

最好的方法是使用Behaviur Subject,这是一个示例:

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

可以创建订阅,并在销毁第一个发出的项之后将其删除。管道是使用Observable作为其输入并返回另一个Observable作为输出的函数,而不修改第一个Observable。角8.1.0。封装:"rxjs": "6.5.3""rxjs-observable": "0.0.7"

  ngOnInit() {

    ...

    // If loading with previously saved value
    if (this.controlValue) {

      // Take says once you have 1, then close the subscription
      this.selectList.pipe(take(1)).subscribe(x => {
        let opt = x.find(y => y.value === this.controlValue);
        this.updateValue(opt);
      });

    }
  }
本文地址:http://javascript.askforanswer.com/ruhehuoqurxjs-subjecthuoobservablededangqianzhi.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!