Stream<T>.periodic constructor

Stream<T>.periodic(
  1. Duration period,
  2. [T computation(
    1. int computationCount
    )]
)

Creates a stream that repeatedly emits events at period intervals.

The event values are computed by invoking computation. The argument to this callback is an integer that starts with 0 and is incremented for every event.

If computation is omitted the event values will all be null.

period must a non-negative Duration.

Implementation

factory Stream.periodic(Duration period,
    [T computation(int computationCount)]) {
  Timer timer;
  int computationCount = 0;
  StreamController<T> controller;
  // Counts the time that the Stream was running (and not paused).
  Stopwatch watch = new Stopwatch();

  void sendEvent() {
    watch.reset();
    T data;
    if (computation != null) {
      try {
        data = computation(computationCount++);
      } catch (e, s) {
        controller.addError(e, s);
        return;
      }
    }
    controller.add(data);
  }

  void startPeriodicTimer() {
    assert(timer == null);
    timer = new Timer.periodic(period, (Timer timer) {
      sendEvent();
    });
  }

  controller = new StreamController<T>(
      sync: true,
      onListen: () {
        watch.start();
        startPeriodicTimer();
      },
      onPause: () {
        timer.cancel();
        timer = null;
        watch.stop();
      },
      onResume: () {
        assert(timer == null);
        Duration elapsed = watch.elapsed;
        watch.start();
        timer = new Timer(period - elapsed, () {
          timer = null;
          startPeriodicTimer();
          sendEvent();
        });
      },
      onCancel: () {
        if (timer != null) timer.cancel();
        timer = null;
        return Future._nullFuture;
      });
  return controller.stream;
}