Sergino
Sergino

Reputation: 10818

How to make observable to repeat

I have a code that emits a new values :

function newValues(): Observable<any> {
    const data$ = new BehaviorSubject<any>({});

    setInterval((x) => {
       data$.next(this.getNewData());
    }, 1000);

   return data$.asObservable();
}

so this way by subscribing to newValues().subscribe() I can receive a new values all the time.

But I think it is not the best way of doing this so I looked at this and so my code became like this:

function newValues(): Observable<any> {
    const data$ = new BehaviorSubject<any>({});

    defer(() => data$.next(this.getNewData()))
      .pipe(
       repeatWhen(notifications => notifications.pipe(delay(1000)))
     );

   return data$.asObservable();
}

However it is seems like the code not working now, after receiving the first value no emissions is taking place.

Any ideas how to fix?

UPDATE:
@evantha suggest to use interval for that use case, I just wonder does that mean that defer....repeatWhen....delay won't work for that use-case?

Upvotes: 0

Views: 1174

Answers (2)

Picci
Picci

Reputation: 17762

I think your question contains some points which are different one from each other.

First point: get a sequence of values (i.e. create a stream)

In the first code snippet you define a function newValues() which returns an Observable which will emit a sequence of values, each value being calculated by the function getNewData() called every 1000 ms. To do so you create a BehaviorSubject and then call next on it with an interval.

If this is what you want, probably the use of rxjs interval function is the right way to go as suggested by @evantha. It is simpler and clearer, at least in my opinion.

Second point: why the second snippet does not work

The reason is simple. You call the function defer but you do not do anything with the value it returns, rather you simply return the BehaviorSubject you just created which, by its nature, returns the starting value and nothing more, unless somebody calls next on it, which does not happen in the second snippet.

Third point: use repeatWhen to generate a repetition of values

The use of repeatWhen to generate a repetition is a much more nuanced case, and I suggest you to read the documentation. I wish to highlight only one thing. repeatWhen enters in action when its source Observable completes. And when it completes, repeatWhen makes sure that the same source Observable is repeated as soon as the Observable returned by the function passed to repeatWhen as parameter emits. You can not easily imagine to have a BehaviorSubject as source for repeatWhen since you normally do not complete a Subject. The addition of delay makes the case even more complicated.

The example where both delay and repeatWhen are used refers to a specific use case: polling a resource using an async function, for instance polling a remote system using an hppt call. In this case you may want to use a combination of delay and repeatWhen to avoid having overlapping calls. But this is a very specific requirement.

Upvotes: 1

evantha
evantha

Reputation: 54

What you need is interval function.


    function newValues(): Observable {
      return interval(1000).pipe(mapTo(getNewData()));
    }

you may subscribe to it like this


    const mySubscription = newValues().subscribe(r => {
      console.log(r);
    });

and when you do not need it anymore make sure to unsubscribe it to avoid any memory leaks.


    mySubscription.unsubscribe();

Upvotes: 1

Related Questions