Skip to content

Instantly share code, notes, and snippets.

@juliangruber
Created July 22, 2012 19:06
Show Gist options
  • Save juliangruber/3160726 to your computer and use it in GitHub Desktop.
Save juliangruber/3160726 to your computer and use it in GitHub Desktop.
Pubsub in Dart
class Pubsub {
Map channels;
Pubsub() {
channels = new Map();
}
subscribe(String channel, Function cb) {
if (channels[channel] == null) {
channels[channel] = new List<Function>();
}
channels[channel].add(cb);
}
publish(String channel, var message) {
for (Function cb in channels[channel]) {
try {
cb(message);
} catch (final Exception e) {
print(e);
}
}
}
unsubscribe(String channel, Function fun) {
if (channels[channel] != null) {
int i = channels[channel].indexOf(fun);
if (i > -1) {
channels[channel].removeRange(i, 1);
}
}
}
}
void main() {
Pubsub pubsub = new Pubsub();
void printMessage(var message) {
print(message);
}
pubsub.subscribe('123', printMessage); // subscribes on channel `123`
pubsub.publish('123', 'a message'); // prints out `a message`
pubsub.unsubscribe('123', printMessage); // unsubscribes from channel `123`
pubsub.unsubscribe('1234', printMessage); // tries unsubscribing from channel `1234`
pubsub.publish('123', 'a second message'); // prints out nothing
pubsub.subscribe('123', printMessage); // subscribes again on channel `123`
pubsub.publish('123', 'a third message'); // prints out `a third message`
pubsub.publish('123', ['one', 'two']); // prints the array
}
@filiph
Copy link

filiph commented Nov 16, 2017

Hi, I know this is a very old gist but I found it useful. I just updated the code to enable soundness. Here it is on DartPad, and I'm copypasting below.

class Pubsub<C, T> {
  final Map<C, List<_Callback<T>>> channels = {};

  void subscribe(C channel, _Callback<T> cb) {
    channels.putIfAbsent(channel, () => <_Callback<T>>[]).add(cb);
  }

  void publish(C channel, T message) {
    for (final _Callback<T> cb in channels[channel]) {
      try {
        cb(message);
      } catch (e) {
        print(e);
      }
    }
  }

  void unsubscribe(C channel, _Callback<T> fun) {
    if (channels[channel] != null) {
      channels[channel].remove(fun);
    }
  }
}

enum Channel {
  one, two
}

void main() {
  // A type-safe pubsub.
  final pubsub = new Pubsub<Channel, String>();

  void printMessage(String message) {
    print(message);
  }

  pubsub.subscribe(Channel.one, printMessage);      // subscribes on channel one
  pubsub.publish(Channel.one, 'a message');         // prints out `a message`
  pubsub.unsubscribe(Channel.one, printMessage);    // unsubscribes from channel one
  pubsub.unsubscribe(Channel.two, printMessage);    // tries unsubscribing from channel two
  pubsub.publish(Channel.one, 'a second message');  // prints out nothing
  pubsub.subscribe(Channel.one, printMessage);      // subscribes again on channel one
  pubsub.publish(Channel.one, 'a third message');   // prints out `a third message`
  
  // A dynamic pubsub.
  final dynamicPubsub = new Pubsub();
  
  dynamicPrint(var message) {
    print(message);
  }
  
  dynamicPubsub.subscribe("123", dynamicPrint);     // subscribes again on channel `123`
  dynamicPubsub.publish("123", ['one', 'two']);     // prints the array
}

typedef _Callback<T> = void Function(T);

Also worth mentioning that most modern Dart code would just use Stream for pubsub functionality (namely, broadcast streams).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment