通过distinctUntilChanged

时间:2018-03-21 18:35:57

标签: rxjs observable

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

  1. 记住最后一次发射的值,并能够通过getter(BehaviorSubject)
  2. 表示它
  3. 仅在值更改时发出
  4. 它必须具有强类型,以便消费者知道getter(又名:BehaviorSubject.getValue())
  5. 我想只是扩展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. 还有另一种首选方式吗?

2 个答案:

答案 0 :(得分: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);
    }

}

答案 1 :(得分:0)

原来我的想法导致调用堆栈超出问题。我假设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()
        }
    );
}