| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- import 'dart:async';
- import 'async_typeof.dart';
- import 'cancel_future.dart';
- class AsyncUtil {
- AsyncUtil._();
- static CancelableFuture<T> retryWithExponentialBackoff<T>(
- FutureCallback<T> callback, int maxRetry, Predicate<dynamic>? predicate) {
- const Duration initialInterval = Duration(seconds: 1);
- int retryCount = 0;
- Timer? timer;
- void attempt(Completer<T> completer) {
- callback().then((value) {
- if (!completer.isCompleted) {
- completer.complete(value);
- }
- }).catchError((error) {
- if (retryCount < maxRetry && (predicate == null || predicate(error))) {
- retryCount++;
- Duration nextInterval = initialInterval * (1 << (retryCount - 1));
- timer = Timer(nextInterval, () => attempt(completer));
- } else {
- if (!completer.isCompleted) {
- completer.completeError(error);
- }
- }
- });
- }
- return CancelableFuture<T>((completer) {
- attempt(completer);
- }, () {
- timer?.cancel();
- });
- }
- static CancelableFuture<T> retryWhen<T>(FutureCallback<T> callback,
- int maxRetry, Duration interval, Predicate<dynamic> predicate,
- [Duration? timeout]) {
- int retryCount = 0;
- Timer? timer;
- Timer? timeoutTimer;
- void attempt(Completer<T> completer) {
- callback().then((value) {
- if (!completer.isCompleted) {
- completer.complete(value);
- }
- }).catchError((error) {
- if ((maxRetry <= 0 || retryCount < maxRetry) && predicate(error)) {
- retryCount++;
- timer = Timer(interval, () => attempt(completer));
- } else {
- if (!completer.isCompleted) {
- completer.completeError(error);
- }
- }
- });
- }
- return CancelableFuture<T>((completer) {
- if (timeout != null) {
- timeoutTimer = Timer(timeout, () {
- if (!completer.isCompleted) {
- completer.completeError(TimeoutException('Operation timed out'));
- }
- });
- }
- attempt(completer);
- }, () {
- timer?.cancel();
- timeoutTimer?.cancel();
- });
- }
- static CancelableFuture<T> retry<T>(
- FutureCallback<T> callback, int maxRetry, Duration interval,
- [Duration? timeout]) {
- return retryWhen(callback, maxRetry, interval, (error) => true, timeout);
- }
- static CancelableFuture<T> delay<T>(
- FutureCallback<T> callback, Duration interval) {
- Timer? timer;
- return CancelableFuture<T>((completer) {
- timer = Timer(interval, () {
- callback().then((value) {
- if (!completer.isCompleted) {
- completer.complete(value);
- }
- }).catchError((error) {
- if (!completer.isCompleted) {
- completer.completeError(error);
- }
- });
- });
- }, () {
- timer?.cancel();
- });
- }
- static StreamController<T> interval<T>(
- IntervalCallback<T> callback, Duration interval, int times,
- {Duration? delay}) {
- Timer? timer;
- StreamController<T> controller = StreamController<T>(onCancel: () {
- timer?.cancel();
- });
- int count = 0;
- void tick() {
- callback(count).then((value) {
- controller.add(value);
- count++;
- if (count < times) {
- timer = Timer(interval, tick);
- } else {
- controller.close();
- }
- }).catchError((error) {
- controller.addError(error);
- controller.close();
- });
- }
- if (delay != null && delay > Duration.zero) {
- timer = Timer(delay, tick);
- } else {
- tick();
- }
- return controller;
- }
- }
|