Index: lib/src/utils.dart |
diff --git a/lib/src/utils.dart b/lib/src/utils.dart |
index 97997d7752521a1e30d13ec6997ad4e04f4a19d2..7d1094edd970080d7e04b8690353efb78633cad2 100644 |
--- a/lib/src/utils.dart |
+++ b/lib/src/utils.dart |
@@ -16,6 +16,9 @@ import 'backend/operating_system.dart'; |
/// The return type should only ever by [Future] or void. |
typedef AsyncFunction(); |
+/// A typedef for a zero-argument callback function. |
+typedef void Callback(); |
+ |
/// A regular expression to match the exception prefix that some exceptions' |
/// [Object.toString] values contain. |
final _exceptionPrefix = new RegExp(r'^([A-Z][a-zA-Z]*)?(Exception|Error): '); |
@@ -141,3 +144,38 @@ String truncate(String text, int maxLength) { |
} |
return '...$result'; |
} |
+ |
+/// Merges [streams] into a single stream that emits events from all sources. |
+Stream mergeStreams(Iterable<Stream> streamIter) { |
+ var streams = streamIter.toList(); |
+ |
+ var subscriptions = new Set(); |
+ var controller; |
+ controller = new StreamController(sync: true, onListen: () { |
+ for (var stream in streams) { |
+ var subscription; |
+ subscription = stream.listen( |
+ controller.add, |
+ onError: controller.addError, |
+ onDone: () { |
+ subscriptions.remove(subscription); |
+ if (subscriptions.isEmpty) controller.close(); |
+ }); |
+ subscriptions.add(subscription); |
+ } |
+ }, onPause: () { |
+ for (var subscription in subscriptions) { |
+ subscription.pause(); |
+ } |
+ }, onResume: () { |
+ for (var subscription in subscriptions) { |
+ subscription.resume(); |
+ } |
+ }, onCancel: () { |
+ for (var subscription in subscriptions) { |
+ subscription.cancel(); |
+ } |
+ }); |
+ |
+ return controller.stream; |
+} |