user6069595
user6069595

Reputation: 43

Delay based on item inside collection

i want to delay emit from observable based on item duration from inside array and print that duration value;id in subscribe ?

[{id:1000},{id:2000},{id:3000},{id:4000}]
                  .map(x => of(x).pipe(delay( x.id)) )            
                     .subscribe(x=>{ console.log (x.id)});

Upvotes: 1

Views: 251

Answers (1)

seniorquico
seniorquico

Reputation: 1459

I think you're close... if you want to project each event into a new observable, then you need to use mergeMap as opposed to map.

import { from, of } from 'rxjs'
import { delay, mergeMap } from 'rxjs/operators'

let events = [{id:1000}, {id:2000}, {id:3000}, {id:4000}]

from(events).pipe(
  mergeMap(event => of(event).pipe(
    delay(event.id),
  )),
).subscribe(event => { console.log(event.id) })

But note that mergeMap will run each event in parallel. For your very specific example, that would translate to each event being output with only 1 second of delay in between. The entire observable would complete in a total of 4 seconds.

If you want the delay to be the time between the events, then you would want to process each sequentially. You could look at concatMap for that:

import { from, of } from 'rxjs'
import { delay, mergeMap } from 'rxjs/operators'

let events = [{id:1000}, {id:2000}, {id:3000}, {id:4000}]

from(events).pipe(
  concatMap(event => of(event).pipe(
    delay(event.id),
  )),
).subscribe(event => { console.log(event.id) })

Again for your very specific example, the above would be waiting one second longer each time in between the events. This observable would complete in a total of 10 seconds.

Upvotes: 2

Related Questions