StreamSubscription and cancelation

180 views
Skip to first unread message

Zdeslav Vojkovic

unread,
May 10, 2013, 4:48:20 AM5/10/13
to mi...@dartlang.org
hi,

I started playing with Dart couple of weeks ago and find it quite interesting, especially the
idea to represent event sequences as streams.

What I find awkward is that a StreamSubscription instance is required to cancel a subscription,
since weak references are not supported.

My understanding is that it might not be required to do it if running in Dart VM (at least eventually)
as it can control the GC, but that it is necessary if going through dart2js.

E.g. I need to observe a number of events and need also to detach from them at some point.
This means I need to collect all the StreamSubscription instances and cancel them later on.
If I need to cancel them at the same time, then I can just dump them into a list and then call

    subscriptions.forEach((sub) => sub.cancel());

However, if I need to detach at different times, then I need to either have a separate StreamSubscription
instances (e.g. as fields of a class) or keep them in a map and look them up by name or something:

    // either
    sub1.cancel();
    // later
    sub2.cancel();

    // or
    subs['event1'].cancel();
    // later
    subs['event2'].cancel();


I find this quite ugly as it pollutes the class state with something which should not really be part of the state.

I understand why obj.onSomeEvent.unsubscribe(handler) is not possible (or at least I think I do),
but some solution which doesn't require caching the subscriptions would make it easier to use streams correctly.

Am I missing something? Are there any ideas to improve on this front?

I couldn't find this issue being discussed in other topics, except that it is mentioned at the end of  https://groups.google.com/a/dartlang.org/d/topic/misc/waZkFDO9YCQ/discussion

Seth Ladd

unread,
May 11, 2013, 3:58:09 PM5/11/13
to mi...@dartlang.org
Hi Zdeslav,

Thanks for the question. You're not the first to ask about this. :)

Dart has lexical scope, even in closures, so access to variables is simpler than some other structured languages. It's possible you can arrange the code where the subscription object is in a lexical scope that's easy to unsubscribe from.

Another scenario: if you only need to listen to the first event, and then unsubscribe, you can try this:

thing.onClick.first.then((e) => foo(e));

No subscription required!

If you can easily detect the condition that allows you to unsubscribe, you could try something like this:

thing.onClick.takeWhile((e) => doIStillWantToBeSubscribed()).listen((e) => doSomething(e));

Just some ideas, do let us know what you come up with!

Zdeslav Vojkovic

unread,
May 12, 2013, 10:02:20 AM5/12/13
to mi...@dartlang.org
hi Set,

thanks for the samples - they are indeed nice for specific scenarios.
however, the consumer part is just a half of the problem, the source side is also a bit awkward as it requires two instances to back each event (or tricks with keeping them in map), as discussed here: http://stackoverflow.com/a/16491115/1663919

anyway, I am happy with Florian's note that the team is looking into it :)

I am trying to port SignalR client lib to Dart and there is a Connection class which provides 10 events, and having 20 backing fields for boilerplate stuff this takes away a lot of elegance from the class :)

hopefully, event support will end up being equally simple as in C# - and this will require some support from language, I don't think it can be implemented with just another class in the library.

e.g. maybe something like:

String event onBark;

where it exposes Stream<String> onBark to the outside (as a broadcast stream), while inside the class it also behaves as a StreamController so you can call onBark.Add("..."); but not from the outside. I do have an EventController<> class for this, which is derived from Stream<> so I can return it as Stream, but also has `Add` so I can use it to fire events - however,  still I need either 1 backing field + Stream getter, or also the other clients can call 'add' if I expose it as EventController.



--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 

Reply all
Reply to author
Forward
0 new messages