Oleg K
Oleg K

Reputation: 5268

RXJS. Lazy observable

I'm playing around with rxjs trying to understand one concept: reactive programming supposed to be lazy. If no one subscriber is attached to an observable, it shouldn't produce values. Here is my example:

const Rx = require('rxjs')

const state = new Rx.Subject()

const changeStateLazy = (args) =>
    Rx.Observable.of(args)
        // some logic, e.g. REST requests
        .do(val => state.next('new state'))

changeStateLazy(42)

const stateListener = state.subscribe(
    val => console.log('state.next: ', val),
    err => console.log('state.error: ', err),
    () => console.log('state.complete'))

How to make the observable (which in function changeStateLazy) lazy, i.e. run some logic... and change the state only if a listener is attached to state subject (in my case it's stateListener)?

Upvotes: 0

Views: 3534

Answers (2)

Oleg K
Oleg K

Reputation: 5268

Here is how I could manage that.

const Rx = require('rxjs')

const lazyStateModifier = new Rx.ReplaySubject(1)
    .map(args => {
        console.log('>some logic. args: ', args)
        return {status: 'OK', result: 'new state'}
    })
    .map(res => res.result)

const state = new Rx.Subject().merge(lazyStateModifier)

const changeStateLazy = (args) =>
    lazyStateModifier.next(args)

console.log('>invoke changeStateLazy')
changeStateLazy(42)

console.log('>subscribe')
state.subscribe(
    val => console.log('state.next: ', val),
    err => console.log('state.error: ', err),
    () => console.log('state.complete'))

Hope there's a better solution, without merging every lazy observable to the state...

Upvotes: 1

user1111
user1111

Reputation: 2030

Not exactly sure what you want to achieve, but if you want to output the LAST value when an observer is subscribed, try "AsyncSubject".

const state = new Rx.AsyncSubject();

For AsyncSubject to work, it needs to call the complete method.

const changeState = () =>
    Rx.Observable.of(1)
       .subscribe(val => {
          state.next('new state');
          state.complete();
        });

You may want to use "BehaviorSubject", "BehaviorSubject", etc. if you want it to behave differently.

Upvotes: 0

Related Questions