Skip to content

Instantly share code, notes, and snippets.

@ottonascarella
Last active June 14, 2020 01:41
Show Gist options
  • Save ottonascarella/e24de96980859303413e3b94028514e0 to your computer and use it in GitHub Desktop.
Save ottonascarella/e24de96980859303413e3b94028514e0 to your computer and use it in GitHub Desktop.
Reactive Web with Dart HTML
<button class="plus">+</button>
<code>0</code>
<button class="minus">-</button>
import 'dart:html' as html;
import 'dart:async';
void main() async {
var plus = html.querySelector('.plus');
var minus = html.querySelector('.minus');
var code = html.querySelector('code');
var pluses = plus.onClick.map((_) => 1);
var minuses = minus.onClick.map((_) => -1);
pluses
.mergeWith(minuses)
.scan(0, (a, b) => a + b)
.listen((v) => code.text = v.toString());
}
extension BetterStream<T> on Stream<T> {
Stream<T> mergeWith(Stream<T> other) {
final controller = StreamController<T>();
final emitter = (T v) => controller.add(v);
final closer = () => controller.close();
final errorEmitter = (e) => controller.addError(e);
var subOther = other.listen(
emitter,
onDone: closer,
onError: errorEmitter,
);
var subThis = this.listen(
emitter,
onDone: closer,
onError: errorEmitter,
);
controller.onCancel = () {
subOther?.cancel();
subThis?.cancel();
controller?.close();
};
return controller.stream;
}
Stream<T> scan(T initialValue, T Function(T a, T b) scanner) {
final controller = StreamController<T>();
var acc = initialValue;
var subThis = this.listen(
(T v) {
acc = scanner(acc, v);
controller.add(acc);
},
onError: (e) => controller.addError(e),
);
controller.onCancel = () {
subThis?.cancel();
controller?.close();
};
return controller.stream;
}
}
body {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100%;
background-color: darkviolet;
}
code {
color: white;
font-size: 24pt;
min-width: 96pt;
text-align: center;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment