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);
});
danday74
  • 52,471
  • 49
  • 232
  • 283

4 Answers4

6
Observable.interval(1000).map(i => MY_ARRAY[i % MY_ARRAY.length])
Meir
  • 14,081
  • 4
  • 39
  • 47
  • 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. – danday74 Dec 19 '16 at 16:14
  • 1
    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 :) – Bazinga Dec 19 '16 at 16:53
  • 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. – Meir Dec 19 '16 at 18:16
  • 1
    I find this more readable `Observable.interval(1000).map(iteration => MY_ARRAY[iteration % MY_ARRAY.length])` – Simon_Weaver Aug 21 '18 at 04:15
  • 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. – 55 Cancri Jun 11 '19 at 23:39
  • @55Cancri - I think it is covered by it. Each invocation of the function makes sure the index is within the array's range by using `i % MY_ARRAY.length`. – Meir Jun 12 '19 at 06:00
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
});
Bazinga
  • 10,716
  • 6
  • 38
  • 63
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))
Asti
  • 12,447
  • 29
  • 38
  • 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 – danday74 Dec 19 '16 at 16:12
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);
});
T. Thuan
  • 1
  • 1
  • 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. – DaveL17 Apr 17 '21 at 11:37