3

I want to emit array items over time (a one second interval between each emit) and when all items have been emitted, repeat over and over.

I know how to do this, but I want to know if there is something more succinct than ..

const MY_ARRAY = ['one','two','three']; const item$ = Rx.Observable.interval(1000).take(MY_ARRAY.length).repeat().map(x => MY_ARRAY[x]); item$.subscribe(x => console.log(x)); 

thanks

output is ..

"one"

"two"

"three"

"one"

"two"

"three"

etc

EDIT:

ATOW, the answers here are summarised as ..

const ARR = ['one', 'two', 'three']; // TAKE YOUR PICK THEY ALL DO THE SAME const item$ = Rx.Observable.interval(1000).map(i => ARR[i % ARR.length]); // const item$ = Rx.Observable.interval(1000).zip(ARR, (a, x) => x).repeat(); // const item$ = Rx.Observable.interval(1000).zip(ARR).repeat().map(x => x[1]); // const item$ = Rx.Observable.interval(1000).take(ARR.length).repeat().map(i => ARR[i]); item$.subscribe((x) => { console.log(x); }); 

4 Answers 4

6
Observable.interval(1000).map(i => MY_ARRAY[i % MY_ARRAY.length]) 
Sign up to request clarification or add additional context in comments.

6 Comments

accepting this. other answers great too but this is shortest (code golf winner) and is the most readable. doesn't make full use of RXJS operators but sometimes simple is best.
This is great answer, but it's not readable for my opinion, every other developer in your team will not understand immediately what the code does. so don't forget to leave a big comment :)
I can understand your point. For me personally it feels more natural. I guess readability is related to how the team is used to do stuff. he zipIterable' with the _` operator might be more complex to some.
I find this more readable Observable.interval(1000).map(iteration => MY_ARRAY[iteration % MY_ARRAY.length])
How would you modify this if the array changed in length over time? For example, what if during the first iteration the array had 23 items, and on the second iteration it had 28? But the iteration should never stop and be seamless, moving from one item to another.
|
5

You can use the zip operator:

const interval$ = Rx.Observable.interval(1000); const items$ = Rx.Observable.from([1,2,3]); const itemsOverTime$ = interval$.zip(items$).repeat(); itemsOverTime$.subscribe(([time, val]) => { console.log(val); // 1 // 2 // 3 // 1 // 2 // 3 }); 

1 Comment

How would you modify this if the array changed in length over time?
1

zip is the go-to operator here, but using Observable.from dumps all values on subscribe, and requires zip to keep a copy of the values. This isn't ideal for large arrays. The original IEnumerable<T> overload for zip is implemented as zipIterable.

const MY_ARRAY = ['one','two','three']; Rx.Observable.interval(1000).zipIterable(MY_ARRAY, (_, v) => v).subscribe(v => console.log(v)) 

1 Comment

zipIterable is not a function in RXJS5? Works when you replace zipIterable() with zip() .. I think you are trying to do something I am not clever enough to understand .. thanks for your answer
0

use zip to combine stream from interval and from so that for each interval time, an value will be emitted. Then you pipe the above observable with repeat operator with no parameter to emit value forever.

const { interval, from, zip } = require('rxjs'); const { repeat } = require('rxjs/operators') const itemsOverTime$ = zip( interval(1000), from(MY_ARRAY) ).pipe(repeat()); itemsOverTime$.subscribe(([time, val]) => { console.log(val); }); 

1 Comment

Code only answers are discouraged here. Please add a description of how your answer solves the problem and why it may be preferable to the other answers already provided.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.