3
votes

I don't have much experience with RxJS, but I was wondering if there is a way to subscribe to an object property change? I am using RxJS 5. I use a BehaviorSubject to push new values to subscribers. The subject contains an object which defines some application settings.

So, what I want to do is, I want an application component to subscribe and get a new value when a specific property changes. Alternatively, I would like the observable to produce a copy of the object for each subscriber - so they don't have a reference to the original object.

My question is similar to this one.

The service that provides application settings:

app.factory('settingsProvider', ['$rootScope', function ($rootScope) {

    let subject = new Rx.BehaviorSubject();

    let updateSettings = function (obj) {

        subject.next(_.merge({}, subject.getValue(), obj));
    };

    return {

        updateSettings: updateSettings,
        getObservable: function () {

            return subject.asObservable();
        }
    };
}]);

In some directive, I would than like to subscribe to a change to some property. I currently have this:

let settings = {};
let settingsSubscription = settingsProvider.getObservable().subscribe(x => settings = x);
1
please post your codeMaxim Shoustin

1 Answers

1
votes

I believe you want the operator distinct. https://rxjs-dev.firebaseapp.com/api/operators/distinct

It's an old question, so I'll give v6 syntax and assume you've updated in the meantime. The concept hasn't changed, so you could apply this approach in v5.

The big error you're making is forcing settings to be reassigned above as a closure. Observables work best as streams, where you pipe one observable into the next and have no side-effects. If we assume you start observing something that's building it like { foo: 1, bar: 2, baz: 3}, we can first map out the prop we want, then distinct on it to ensure we only emit on a change.

const fooUpdate$ = mySub$
  .pipe(
    .map(({ foo }) => foo)
    .distinct()
  );

fooUpdate$.subscribe(val => console.log(val));

// Example of testing it
mySub$.next({ foo: 1, bar: 2 });
mySub$.next({ foo: 1, bar: 3 });
mySub$.next({ foo: 2, bar: 4 });
mySub$.next({ foo: 2, bar: 5 });
mySub$.next({ foo: 2, bar: 5 });
mySub$.next({ foo: 3, bar: 2 });

// 1, 2, 3