'Delay for every element with 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);
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
Solution 1:[1]
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.
Solution 2:[2]
Here is my solution (very clean)
const fakeData = [1,2,3]
loadData$() {
return from(fakeData).pipe(
concatMap(item => of(item).pipe(
delay(1000)
)),
);
}
Solution 3:[3]
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) )
Solution 4:[4]
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));
Solution 5:[5]
Here, you emit in one observable emission the all array. [1,2,3].
You only delay that one emission by 1000 ms. But the emission is still one.
Even if we emit each value on its own, the delay function will only apply to the first emission. The others will come immediately after:
Rx.Observable.create(obs => {
var arr = [1, 2, 3];
arr.forEach(item => obs.next(item));
obs.complete();
}).delay(1000);
There is no magic in the create constructing function. If we want an emission to come every x time:
We could make an interval that emits those values (taken from learnrxjs)
import { Observable } from 'rxjs/Observable';
/*
Increment value every 1s, emit even numbers.
*/
const evenNumbers = Observable.create(function(observer) {
let value = 0;
const interval = setInterval(() => {
observer.next(value);
value++;
}, 1000);
return () => clearInterval(interval);
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Kris Jobs |
| Solution 3 | John |
| Solution 4 | |
| Solution 5 | elpddev |
