Created
February 27, 2025 01:39
-
-
Save PlugFox/4ced7d394fb07ed329f8b69ea154dad1 to your computer and use it in GitHub Desktop.
Go like defer in Dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async' show Future, Zone, scheduleMicrotask; | |
final Object _deferredPushKey = Object(); | |
/// Defers the given [callback] function to be executed after the current zone. | |
/// The callback will be executed in the reverse order of their registration. | |
void defer(void Function() callback) { | |
final push = Zone.current[_deferredPushKey]; | |
if (push is void Function(void Function() callback)) { | |
push(callback); | |
} else { | |
throw StateError('defer() can only be called within runWithDefer()'); | |
} | |
} | |
/// Runs the given [body] function in a new zone with deferred execution support. | |
T runWithDefer<T>(T Function() body, {bool microtask = false}) { | |
void Function()? stack; | |
void push(void Function() callback) { | |
final prev = stack; | |
stack = () { | |
try { | |
callback(); | |
} finally { | |
prev?.call(); | |
} | |
}; | |
} | |
void execute() { | |
final call = stack; | |
if (call == null) { | |
return; | |
} else if (microtask) { | |
scheduleMicrotask(call); | |
} else { | |
call(); | |
} | |
} | |
return Zone.current.fork(specification: null, zoneValues: <Object?, Object?>{_deferredPushKey: push}).run<T>(() { | |
var handled = false; | |
try { | |
final value = body(); | |
assert(value is! Stream<Object?>, 'Stream is not supported by runWithDefer()'); | |
if (value is Future<Object?>) { | |
handled = true; | |
return value..whenComplete(execute); | |
} | |
return value; | |
} on Object { | |
rethrow; | |
} finally { | |
if (!handled) execute(); | |
} | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'defer.dart'; | |
class Client { | |
Client() { | |
print('Client created'); | |
} | |
Future<void> fetch(Object url) => | |
Future.delayed(const Duration(milliseconds: 250), () => print('Client fetched $url')); | |
void close() => print('Client closed'); | |
} | |
void main(List<String> arguments) => runWithDefer<void>(() async { | |
final client = Client(); | |
defer(() => print('Program finished')); | |
defer(client.close); | |
await client.fetch('http://a.ru'); | |
await client.fetch('https://b.com'); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment