progress_future 0.1.0 progress_future: ^0.1.0 copied to clipboard
A Future that reports the progress of its completion, and various progress bars to show it in CLI.
A Future that reports the progress of its completion, and various progress bars to show it in CLI.
Usage #
Tracking progress #
Tracking progress as an integer value #
- Create
IntProgressUpdater
object. - Write a function that returns a regular
Future
and kicks the updater object as it progresses. - Wrap that function's
Future
intoIntProgressFuture
. await
it as you would with any otherFuture
. Use itsevents
to track the progress of the function.
Future<void> main() async {
final future = wait(5);
future.events.listen((event) {
print('${event.progress} seconds elapsed.');
});
print(await future);
}
IntProgressFuture<String> wait(int seconds) {
final updater = IntProgressUpdater(total: seconds);
final generate = (int seconds) async {
for (int n = 0; n < seconds; n++) {
updater.setProgress(n);
await Future.delayed(const Duration(seconds: 1));
}
return 'Waited $seconds seconds.';
};
return IntProgressFuture.wrap(generate(seconds), updater);
}
Output:
1 seconds elapsed.
2 seconds elapsed.
3 seconds elapsed.
4 seconds elapsed.
Waited 5 seconds.
Tracking progress as a double value #
Use DoubleProgressUpdater
and DoubleProgressFuture
if your progress measures as double
and not int
.
If your progress is from 0 to 1, use DoubleProgressUpdater.normalized()
convenience constructor.
It's also defined for IntProgressUpdater
but makes less sense there.
Tracking intermediate data in addition to the progress #
In addition to the progress, you can report custom data with each event. For this, use
DataIntProgressFuture
andDataIntProgressUpdater
.DataDoubleProgressFuture
andDataDoubleProgressUpdater
.
import 'package:clock/clock.dart';
import 'package:progress_future/progress_future.dart';
Future<void> main() async {
final future = waitWithEta(Duration(seconds: 5));
future.events.listen((event) {
print('${event.progress} seconds elapsed, ${event.data} left.');
});
print(await future);
}
DataDoubleProgressFuture<String, Duration> waitWithEta(Duration duration) {
final updater = DataDoubleProgressUpdater<Duration>(
total: duration.inMicroseconds / Duration.microsecondsPerSecond,
);
Future<String> generate(Duration duration) async {
final start = clock.now();
final end = start.add(duration);
while (true) {
final now = clock.now();
final secondsElapsed =
(now.microsecondsSinceEpoch - start.microsecondsSinceEpoch) /
Duration.microsecondsPerSecond;
final left = end.difference(now);
if (left.inMicroseconds <= 0) {
break;
}
updater.setProgress(secondsElapsed, left);
await Future.delayed(const Duration(milliseconds: 500));
}
return 'Waited for $duration.';
}
return DataDoubleProgressFuture.wrap(generate(duration), updater);
}
Output:
0.507785 seconds elapsed, 0:00:04.492215 left.
1.010969 seconds elapsed, 0:00:03.989031 left.
1.512462 seconds elapsed, 0:00:03.487538 left.
2.013939 seconds elapsed, 0:00:02.986061 left.
2.516299 seconds elapsed, 0:00:02.483701 left.
3.018368 seconds elapsed, 0:00:01.981632 left.
3.519966 seconds elapsed, 0:00:01.480034 left.
4.022319 seconds elapsed, 0:00:00.977681 left.
4.524792 seconds elapsed, 0:00:00.475208 left.
Waited for 0:00:05.000000.
Use cases for this include:
- Reporting the ETA if it's non-linear and the client can't just extrapolate the elapsed time.
- Reporting intermediate values if you compute some value in iterations.
Wrapping a Future without progress #
Sometimes you don't have a progress information but still need to return ProgressFuture
from your method to maintain a consistent API.
In this case, use ProgressFuture.wrapWithoutProgress(future)
constructor.
Wrapping a synchronous value #
Use ProgressFuture.value(value)
.
Printing the progress #
Printing dots #
Use CharacterProgressPrinter
:
Future<void> main() async {
final future = wait(20);
CharacterProgressPrinter(future);
print(await future);
}
IntProgressFuture<String> wait(int count) {
final updater = IntProgressUpdater(total: count);
Future<String> generate(int count) async {
for (int n = 0; n < count; n++) {
updater.setProgress(n);
await Future.delayed(const Duration(milliseconds: 200));
}
return 'Done.';
}
return IntProgressFuture.wrap(generate(count), updater);
}
Output:
...................
Done.