danschultz / frappe

A Dart package for functional reactive programming

Home Page:http://pub.dartlang.org/packages/frappe

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PropertyController?

jonaskello opened this issue · comments

Not sure I am doing this right but I feel the need for a PropertyController (or SignalController). I currently do:

  class SignalController {
    final Property signal;
    final StreamController controller;

    SignalController(this.signal, this.controller);
  }

   var controller = new StreamController();
   var signal = new Property.fromStream(controller.stream);
   var signalController = new SignalController(signal, controller);

I store the SignalController in order to return the Property to anyone who wants to subscribe, and also add new values to the Property. If this is the way it is supposed to play out, then maybe something like the SignalController could be added to the library?

I like it. I've been doing something like this is some of my projects as well. I call them channels (from Elm), and they expose both an EventStream and a Property. Perhaps calling them Property|SignalController is better in Dart land.

They're roughly implemented like the following, and they're responsible for creating the StreamController internally. They're public constructors follow the same API as StreamController for consistency.

class Channel<T> implements StreamController {
  EventStream<T> get stream => property.asEventStream();
  final Property<T> property;

  Channel._(StreamController<T> controller) : property = new Property.fromStream(controller);

  Channel({bool sync: false}) : this._(new StreamController(sync: sync));

  Channel.broadcast({bool sync: false}) : this._(new StreamController.broadcast(sync: sync));
}

I've been calling mine a ControlledProperty. Seems it's not just me that found the need for it then ;-)

I expanded the Channel example into this workable code:

class SignalController<T> implements StreamController {

  final StreamController<T> _controller;
  final Property<T> signal;

  SignalController._(StreamController<T> controller) : _controller = controller, signal = new Property.fromStream(controller.stream);

  SignalController({bool sync: false}) : this._(new StreamController(sync: sync));

  SignalController.broadcast({bool sync: false}) : this._(new StreamController.broadcast(sync: sync));

  EventStream<T> get stream => signal.asEventStream();

  StreamSink<T> get sink => _controller.sink;

  bool get isClosed => _controller.isClosed;

  bool get isPaused => _controller.isPaused;

  bool get hasListener => _controller.hasListener;

  Future get done => _controller.done;

  Future close() => _controller.close();

  void add(T event) => _controller.add(event);

  Future addStream(Stream<T> source, {bool cancelOnError: true}) =>
  _controller.addStream(source, cancelOnError: cancelOnError);

  void addError(Object error, [StackTrace stackTrace]) =>
  _controller.addError(error, stackTrace);
}

I think the addition of SignalController in combination with renaming Property to Signal would be a nice addition. Then we have StreamController / Stream and SignalController / Signal.

@jonaskello

Signals also have a concept of an initial value. We might need to add an optional param to the constructors for this.