【问题标题】:rxjs BehaviorSubject that emits via distinctUntilChanged通过 distinctUntilChanged 发出的 rxjs BehaviorSubject
【发布时间】:2018-08-31 00:52:31
【问题描述】:

我想实现一个具有 3 个特定属性的 Observable / Subject

  1. 记住最后发出的值并能够通过 getter (BehaviorSubject) 将其显示出来
  2. 仅在值更改时发出
  3. 它必须有一个强类型,以便消费者知道 getter 可用(又名 BehaviorSubject.getValue())

我正在考虑扩展 BehaviorSubject,但要确保我不会根据我的新手理解引入任何潜在的陷阱。

export class DistinctUntilChangedBehaviorSubject<T, TValue> extends BehaviorSubject<T> {
    constructor(
        initialValue: T,
        private _distinctKeySelector?: (value: T) => TValue,
        private _comparer?: _Comparer<TValue, boolean>
    ) {
        super(initialValue);
    }

    public subscribe() {
        // I'm particularly interested in knowing if this has any gotchas. 
        // Mostly things like creating subscriptions that don't get disposed as expected.
        return super.distinctUntilChanged(
            this._distinctKeySelector,
            this._comparer
        ).subscribe.apply(this, arguments);
    }
}

所以 2 个问题:

  1. 这似乎是一种合理的方法/这里有什么陷阱吗?
  2. 还有其他首选方法吗?

【问题讨论】:

    标签: rxjs observable


    【解决方案1】:

    我真的不知道为什么,但我更喜欢组合而不是扩展。

    所以我会按照这些思路做一些事情

    import {BehaviorSubject} from 'rxjs';
    
    export class BehaviourSubjectAugmented<T> {
        bs: BehaviorSubject<T>;
    
        constructor(initialValue: T, private comparer: (p: T, q: T) => boolean) {
            this.bs = new BehaviorSubject(initialValue);
        }
    
        getValue() {
            return this.bs.getValue();
        }
    
        asObservable() {
            return this.bs.asObservable()
                            .distinctUntilChanged(this.comparer);
        }
    
        complete() {
            return this.bs.complete();
        }
        next(value: T) {
            return this.bs.next(value);
        }
    
    }
    

    【讨论】:

    • 我也更喜欢构图,只是不想包装太多东西。在您的示例中,当您订阅 BehaviourSubjectAugmented 对象时是否会调用 asObservable() ,还是必须订阅 asObservable() 的结果?
    • 因为它现在被编码,你需要做behaviourSubjectAugmented.asObservable().subscribe()
    • 嗯,猜测这也意味着除非您调用 asObservable,否则不会出现链式运算符。
    • asObservable() 确保您不能使用next 方法来发出值(请参阅stackoverflow.com/questions/36986548/…stackoverflow.com/questions/42272821/observable-vs-asobservable)。如果这对你来说不重要,那么你可以直接使用bs属性
    【解决方案2】:

    原来我最初的想法导致调用堆栈超出问题。我假设 distinctUntilChanged 必须在内部调用 subscribe 从而导致无限递归。

    我最终找到了一种更简单的方法来获得所需的内容,只需将方法添加到 ISubject 实例即可。

    function distinctUntilChangedBehaviorSubject(
        initialValue: number
    ): ISubject<number> & { getValue(): number } {
        const observer = new BehaviorSubject<number>(initialValue);
        const observable = observer.distinctUntilChanged();
    
        const subject: ISubject<number> = Subject.create(
            observer,
            observable
        );
    
        return Object.assign(
            subject,
            {
                getValue: () => observer.getValue()
            }
        );
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-07
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 2016-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多