web-dev-qa-db-ja.com

RxJS別個のUntilChanged-オブジェクト比較

オブジェクトのストリームがあり、現在のオブジェクトが前のオブジェクトと同じでないかどうかを比較する必要があります。この場合、新しい値を出力します。私はdistinctUntilChanged演算子が私が望んでいることを正確に実行する必要があることを発見しましたが、何らかの理由で、最初の演算子以外は値を出力しません。私がdistinctUntilChanged値を削除すると、通常どおりに出力されます。

私のコード:

export class SettingsPage {
    static get parameters() {
        return [[NavController], [UserProvider]];
    }

    constructor(nav, user) {
        this.nav = nav;
        this._user = user;

        this.typeChangeStream = new Subject();
        this.notifications = {};
    }

    ngOnInit() {

        this.typeChangeStream
            .map(x => {console.log('value on way to distinct', x); return x;})
            .distinctUntilChanged(x => JSON.stringify(x))
            .subscribe(settings => {
                console.log('typeChangeStream', settings);
                this._user.setNotificationSettings(settings);
            });
    }

    toggleType() {
        this.typeChangeStream.next({
            "sound": true,
            "vibrate": false,
            "badge": false,
            "types": {
                "newDeals": true,
                "nearDeals": true,
                "tematicDeals": false,
                "infoWarnings": false,
                "expireDeals": true
            }
        });
    }

    emitDifferent() {
        this.typeChangeStream.next({
            "sound": false,
            "vibrate": false,
            "badge": false,
            "types": {
                "newDeals": false,
                "nearDeals": false,
                "tematicDeals": false,
                "infoWarnings": false,
                "expireDeals": false
            }
        });
    }
}
23
Daniel Suchý

同じ問題があり、JSON.stringifyを使用してオブジェクトを比較することで修正しました。

.distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))

汚いが動作するコード。

29
Mehdi Benmoha

ようやく問題がどこにあるのかわかりました。 V4以前のバージョンのRxJSに問題があり、V5とはパラメーターの順序が異なります。

RxJS 4:

differentUntilChanged = function(keyFn、comparer)

RxJS 5:

distinctUntilChanged = function(comparer、keyFn)

今日のすべてのドキュメントで、V4パラメータの順序を見つけることができます。これに注意してください!

21
Daniel Suchý

とにかくアプリケーションにlodashがある場合は、lodashのisEqual()関数を利用するだけで済みます。この関数は、深い比較を行い、distinctUntilChanged()のシグネチャと完全に一致します。

.distinctUntilChanged(isEqual),

または、_利用可能(最近は推奨されません):

.distinctUntilChanged(_.isEqual),
10
hoeni

Mehdiのソリューションは高速ですが、順序が維持されないと機能しません。 deep-equal または fast-deep-equal ライブラリのいずれかを使用:

.distinctUntilChanged((a, b) => deepEqual(a, b))
3
Wildhammer

RxJS v6 +以降には、distinctUntilKeyChangedがあります

https://www.learnrxjs.io/operators/filtering/distinctuntilkeychanged.html

const source$ = from([
  { name: 'Brian' },
  { name: 'Joe' },
  { name: 'Joe' },
  { name: 'Sue' }
]);

source$
  // custom compare based on name property
  .pipe(distinctUntilKeyChanged('name'))
  // output: { name: 'Brian }, { name: 'Joe' }, { name: 'Sue' }
  .subscribe(console.log);
2
Whisher

値を変更可能に変更すると、他の回答はどれも機能しません。変更可能なデータ構造で作業する必要がある場合は、distinctUntilChangedImmutableを使用できます。値、および比較関数が渡されない場合、以前の値と現在の値が互いに等しいことをアサートします(===アサーションではありません)。

0
Tom