Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delay for every element with RXJS

Tags:

rxjs

I'm using RxViz to simulate different actions that comes every 1 sec. When I try

Rx.Observable.create(obs => {
  obs.next([1, 2, 3]); // or could be ['aaa', 'bbbb', 'ccc']
  obs.complete();
}).delay(1000);

on https://rxviz.com

or on my own with a console.log

it keeps displaying the three number 1, 2, 3 at the same time

There's a post about this same problem, but none of the answer works for me. I'm using Rx last version 6

How can I create an observable with a delay

[EDIT] The array can contains anything like number, string or any object

like image 612
John Avatar asked Jun 16 '18 10:06

John


People also ask

How do you delay in RxJS?

In RxJS you can set the per-item delay in two ways: by passing a number of milliseconds into the delay operator (which will delay each emission by that amount of time), or by passing in a Date object (which will delay the beginning of the sequence of emissions until that absolute point in time).

How do I add a delay to observable?

Subscribe to a source observable. When a new value arrives from a source observable, add the value to internal cache and start a delay interval for that value. Once the interval elapses, send the corresponding value to the observer. Once the source observable completes, send the complete notification to the observer.

What is concatMap in RxJS?

concatMap operator is basically a combination of two operators - concat and map. The map part lets you map a value from a source observable to an observable stream. Those streams are often referred to as inner streams.


4 Answers

If you want to delay each value (by 1 sec for example), you may do something like the following:

 Rx.Observable.create(obs => {
      obs.next([1, 2, 3]);
      obs.complete();
    })
      .pipe(
        // make observable to emit each element of the array (not the whole array)
        mergeMap((x: [any]) => from(x)),
        // delay each element by 1 sec
        concatMap(x => of(x).pipe(delay(1000)))
      )
      .subscribe(x => console.log(x));
  }

Here I did not modify the internals of the observable created by you. Instead, I just take your observable and apply appropriate operations to achieve what you seem to be expecting.

like image 160
siva636 Avatar answered Oct 21 '22 18:10

siva636


Here is my solution (very clean)

const fakeData = [1,2,3]

loadData$() {
    return from(fakeData).pipe(
      concatMap(item => of(item).pipe(
        delay(1000)
      )),
    );
  }
like image 42
Kris Jobs Avatar answered Oct 21 '22 16:10

Kris Jobs


This one works by modifying a little bit @siva636's answer

Rx.Observable.create(obs => { 
  obs.next(1); 
  obs.next(2); 
  obs.next(3); 
  obs.complete(); 
}.concatMap(x=>Rx.Observable.of(x) .delay(1000) )
like image 4
John Avatar answered Oct 21 '22 16:10

John


Here is a succinct way that builds on the other responses.

from([...Array(10).keys()]).pipe(
    concatMap(x => of(x).pipe(delay(1000)))
).subscribe(y => console.log(y))

A more RxJs native version would be as follows.

const myInterval = rxjs.interval(1000);
myInterval.pipe(rxjs.operators.take(10)).subscribe(x => console.log(x));
like image 2
Alejandromusic Avatar answered Oct 21 '22 16:10

Alejandromusic