Search code examples
typescriptrxjsrepeatsubjectswitchmap

Repeating the emission of a Subject


I'm not getting why the following BehaviourSeubject is not emitting three times

const numbers = [1, 2, 3, 4]
const urls$ = new BehaviorSubject<number[]>(numbers)

urls$.pipe(repeat(3)).subscribe(console.log)

Also, what is the semantic of the following?

urls$.pipe(switchMap(arr => from(arr)), repeat(3)).subscribe(console.log)

I would expect to repeat three times as well but the only working case is

urls$.pipe(switchMap(arr => from(arr).pipe(repeat(3)))).subscribe(console.log)

Solution

  • By the definition of repeat operator,

    The repeat(count) operator returns an Observable that will resubscribe to the source stream when the source stream completes, at most the count times.

    Thus, the source$ which is urls$ in this case needs to be completed so that repeat can act, but urls$ is a behavior subject and once you signal completion for the behavior subject with urls$.complete(), you won't be able to receive anything in the subscription. Hence, if you want to have the values emitted by the behavior subject, the repeat operator can not be used.

    Now how do we solve this problem?

    The expand operator comes to our rescue. [expand][1] recursively projects the values emitted by the source observable. With expand & take, we'll be able to achieve the desired result.

    const numbers = [1, 2, 3, 4];
    const urls$ = new BehaviorSubject<number[]>(numbers);
    
    urls$
      .pipe(expand(result => urls$), take(3))
      .subscribe(console.log);