4

I want to emit values in a stream from a list with a specific delay in dart.

So, from [1,2,3], which is a regular List I want to emit values like 1...2...3 in separated events.

I tried something like this

List<int> myList = [1,2,3];
Subject _current = BehaviorSubject<int>();
Stream<int> get current$ => _current.stream.delay(Duration(seconds:1));

myList.forEach(current.add);

But I get ...123 instead, so this is delaying the whole stream 1 seconds, rather than every value in the list.

Any ideas? Thanks

David
  • 3,364
  • 10
  • 41
  • 84

6 Answers6

4

If you'd like to avoid rxdart, you can use simple transformation function like:

Stream<T> streamDelayer<T>(Stream<T> inputStream, Duration delay) async* {
  await for (final val in inputStream) {
    yield val;
    await Future.delayed(delay);
  }
}

void main() {
  var s = Stream.fromIterable([1, 2, 3]);
  streamDelayer(s, Duration(seconds: 1)).forEach(print);
}
user2424794
  • 209
  • 1
  • 8
1

One solution using rxdart 0.25.0:

final Stream<int> stream = 
    Rx.range(1, 3)
      .asyncExpand((event) => 
        event == 1
        ? Stream.value(event) // return first value immediately
        : Rx.timer(event, Duration(seconds: 1))
    );
David Lawson
  • 7,802
  • 4
  • 31
  • 37
1

using interval from rxdart package

Stream.fromIterable(List<int>.generate(100, (i) => i))
        .interval(Duration(milliseconds: 10))
        .listen((v) {
      print(v);
});
Ali80
  • 6,333
  • 2
  • 43
  • 33
0

The rxdart

package provides a delay transformer or method that does that

new Observable.fromIterable([1, 2, 3, 4])
  .delay(new Duration(seconds: 1))
  .listen(print); // [after one second delay] prints 1, 2, 3, 4 immediately

There are others like debounce

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks, but that's doing the same that I have, it waits for 1 second and then prints immediately; what I want is to print 1, wait 1 second, print 2, wait 1 second, print 3, wait 1 second, print 4, wait 1 second. – David Jan 03 '19 at 15:26
  • 1
    I actually got the answer from rxdart itself, using concatMap, thanks. – David Jan 03 '19 at 15:35
0

I managed to get it working

Observable.range(myList)
  .concatMap((i) =>
    new Observable.timer(i, new Duration(seconds: 1))
  .listen(print);

From the rxdart documentation itself. Thanks Günter for the good tip.

David
  • 3,364
  • 10
  • 41
  • 84
0

Best solution using StreamController, which gives you the ability to control the stream using pause and resume as follows:

List<int> myList = [1, 2, 3];
StreamController current = StreamController();
late StreamSubscription listenController;

void waitFunction() async {
  listenController.pause();
  await Future.delayed(const Duration(seconds: 2));
  listenController.resume();
}

myList.forEach(current.add);

listenController = current.stream.listen((event) async {
  print(event);
  waitFunction();
});
Nightcap79
  • 620
  • 7
  • 13