Damian C
Damian C

Reputation: 2171

RxJS emit array of strings, one second apart from each other

I have a block of code that is responsible for taking an Observable<string[]>, then mapping that to Observable<string> and emitting the values 1 second apart from each other.

Think of this like a message ticker on a website.

My current code is working below:

    const arrayOfStrings$ = of([
        'Warming things up',
        'Getting things ready',
        'Welcome'
    ]);

    this.messages$ = arrayOfStrings$.pipe(
        switchMap((messages) => from(messages).pipe(
            concatMap((innerMessage) => of(innerMessage).pipe(delay(1000))),
        )),
        tap((message) => {
            console.log(`Message: ${message}`);
        })
    );

Is there a better way to do this with less code? It's mainly the switchMap() and concatMap() inside each other that is bothering me.

Thanks for any help and suggestions.

Edit: This is a simplified version of what I have running in my actual project. I am just trying to find an easier way to go from an Observable<string[]> to an Observable and delay each emission one second apart after each emission

Upvotes: 4

Views: 1243

Answers (3)

martin
martin

Reputation: 96899

You can use the concatMap() and delay() operators to make sure that each emission will be delivered one-by-one with a specified time interval.

const arrayOfStrings = [
  'Warming things up',
  'Getting things ready',
  'Welcome'
];

(from(arrayOfStrings)
  .pipe(
    concatMap(message => 
      of(message).pipe(delay(1_000))
    ),
  )
  .subscribe()
);

Upvotes: 7

Juri Naidenov
Juri Naidenov

Reputation: 1885

of('one', 'two', 'three')
  .pipe(zipWith(interval(1000)))
  .subscribe(console.log)

or if you want to start immediately replace interval with

timer(0, 1000)

Upvotes: 1

Harald Gliebe
Harald Gliebe

Reputation: 7564

I would use the following code:

const arrayOfStrings$ = of([
  'Warming things up',
  'Getting things ready',
  'Welcome'
]);

arrayOfStrings$.pipe(
  mergeMap((a) => a),
  zip(timer(1000, 1000)),
  map(([a]) => a),
  tap(message => {
    console.log(`Message: ${message}`);
  })
);

Upvotes: 0

Related Questions