Rxjs operator delay doesn't delay the emitted values from of - rxjs

I would like to emit a value every second. So I created the following code:
of(1, 2, 3, 4, 5, 6, 7, 8)
.pipe(map(val => val + 10), delay(1000))
.subscribe(console.log);
DEMO
But this code still prints all the values at once with an initial delay of 1 second. But how can you delay every value?

You can achieve that by using RxJS interval function like the following:
interval(1000)
.pipe(map((val) => val + 10))
.subscribe(console.log);

Related

RxJs Zip only takes the first value from the sent stream

I have the following code using RxJs Zip operator:
of(1, 2, 3)
.pipe(zip(of(5), of(10)))
.subscribe((a) => console.log(a));
The output will be
[1, 5, 10]
But what happened to the 2 and 3 values initialized at of(1, 2, 3)?
The inner observables of(5) and of(10) only have one element. The static method zip() will only emit when all observable emit a corresponding notification.
For eg.
of(1, 2, 3)
.pipe(zip(of(5, 6, 7), of(10, 11, 12)))
.subscribe((a) => console.log(a));
will emit
[1, 5, 10]
[2, 6, 11]
[3, 7, 12]
I must also stress here that the static method zip() is deprecated and has since been replaced by the zip() function. Using the new zip() the equivalent for the above would be
import { of, zip } from 'rxjs';
zip(
of(1, 2, 3),
of(5, 6, 7),
of(10, 11, 12)
).subscribe((a) => console.log(a));

Any way to reset Interval value if a certain condition met?

Suppose I have an array of integers and I want to iterate over this array in a interval of one second, the current second being the index of the array. Once the index reaches the end, I want to reset the interval value. Whats the right approach to achieve this behavior?
Stackblitz example
Code:
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
interval(1000)
.pipe(
tap(second => {
if (array[second]) {
console.log(array[second]);
} else {
//reset interval to run in a cyclic manner?
}
})
).subscribe();
So you want to repeat the same sequence indefinatelly.
import { from, of } from "rxjs";
import { concatMap, repeat, delay } from "rxjs/operators";
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
from(array)
.pipe(
concatMap(second => of(second).pipe(
delay(second * 1000),
)),
repeat(),
)
.subscribe(console.log);
Live demo: https://stackblitz.com/edit/rxjs-interval-pmlj6e

Rxjs - emit if the pair appears

Question about rxjs puzzle.
I have a random numbers stream.
the number takes [0-9] numbers. so the stream looks like:
0, 4, 2, 8, 9, 0, 3, 9, ...
I want to emit true if number 9 after 5. In other words, if the pair [5, 9] appears in the stream.
what the pipe should be?
Example code is here:
import { interval } from "rxjs";
import { map } from "rxjs/operators";
const numbers =
interval(500).pipe(map(() => Math.floor(Math.random() * 10))); // it takes [0-9] numbers
numbers.pipe(
// what the pipe should be?
).subscribe(console.log);
You could use the pairwise() operator:
src$.pipe(
pairwise(),
map(([prev, crt]) => prev === 5 && crt === 9)
)

How can I have only X observables active at a time?

I'm using RxJS v6, but the answer could apply to RxJS v5 as well.
I'd like to make it so if I have say 8 values, I would only have 4 actively being processed at a time.
The code I have right now sends in 4 items, then waits till all 4 finish, then sends in the next 4. I'd like it to send in the first 4, then as an observable completes, another one comes in to be processed.
from([1, 2, 3, 4, 5, 6, 7, 8])
.pipe(
bufferCount(4),
concatMap(values => (
from(values)
.pipe(
mergeMap(value => (
timer(1000) // Async stuff would happen here
.pipe(
mapTo(value),
)
)),
)
)),
)
.subscribe(console.log)
You have to use the second parameter of mergeMap, which is a number that allows to specify the concurrency level you want.
So your code could look like
from([1, 2, 3, 4, 5, 6, 7, 8])
.pipe(
map(val => of(val)),
mergeMap(val => val, 4),
)
.subscribe(console.log)
or
of([1, 2, 3, 4, 5, 6, 7, 8])
.pipe(
mergeMap(val => val, 4),
)
.subscribe(console.log)
Consider that concatMap is mergeMap with concurrency level set to 1.
Read this SO post for more details on mergeMap.

Why does switchMap operator only emit the last value when used with a promise?

I have some trouble to understand this. When I use the switchMap operator with an Observable it emits all the values as expected:
Observable.from([1, 2, 3, 4, 5])
.do(console.log)
.switchMap(i => Observable.of('*' + i))
.do(console.log)
.subscribe();
Results:
1
*1
2
*2
3
*3
4
*4
5
*5
But when I replace the the Observable by a Promise I get a different behaviour:
Observable.from([1, 2, 3, 4, 5])
.do(console.log)
.switchMap(i => new Promise((resolve) => resolve('*' + i)))
.do(console.log)
.subscribe();
Results:
1
2
3
4
5
*5
This works as expected. The unexpected behaviors as you said is because Observable.from and Observable.of are always strictly synchronous while new Promise necessarily doesn't (I'm not sure about the specification so maybe that's what Promise has to do in all browsers).
Anyway you can force Observable.from emit asynchronously by passing the async Scheduler.
import { Observable } from 'rxjs';
import { async } from 'rxjs/scheduler/async';
Observable.from([1, 2, 3, 4, 5], async)
.do(console.log)
.switchMap(i => new Promise((resolve) => resolve('*' + i)))
.do(console.log)
.subscribe();
Now every emission is in a new frame just like Promise and the output is as you expected.
See live demo (open console): https://stackblitz.com/edit/rxjs5-gfeqsn?file=index.ts
Try mergeMap, maybe it is what you are looking for.

Resources