|
|
@@ -9,15 +9,12 @@ class AsyncUtil {
|
|
|
AsyncUtil._();
|
|
|
|
|
|
static CancelableFuture<T> retryWithExponentialBackoff<T>(
|
|
|
- FutureCallback<T> callback,
|
|
|
- int maxRetry,
|
|
|
- Duration initialInterval,
|
|
|
- Predicate<dynamic> predicate) {
|
|
|
- Completer<T> completer = Completer<T>();
|
|
|
+ FutureCallback<T> callback, int maxRetry, Predicate<dynamic> predicate) {
|
|
|
+ const Duration initialInterval = Duration(seconds: 1);
|
|
|
int retryCount = 0;
|
|
|
Timer? timer;
|
|
|
|
|
|
- void attempt() {
|
|
|
+ void attempt(Completer<T> completer) {
|
|
|
callback().then((value) {
|
|
|
if (!completer.isCompleted) {
|
|
|
completer.complete(value);
|
|
|
@@ -26,7 +23,7 @@ class AsyncUtil {
|
|
|
if (retryCount < maxRetry && predicate(error)) {
|
|
|
retryCount++;
|
|
|
Duration nextInterval = initialInterval * (1 << (retryCount - 1));
|
|
|
- timer = Timer(nextInterval, attempt);
|
|
|
+ timer = Timer(nextInterval, () => attempt(completer));
|
|
|
} else {
|
|
|
if (!completer.isCompleted) {
|
|
|
completer.completeError(error);
|
|
|
@@ -35,28 +32,27 @@ class AsyncUtil {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- attempt();
|
|
|
-
|
|
|
- return CancelableFuture<T>(() {
|
|
|
+ return CancelableFuture<T>((completer) {
|
|
|
+ attempt(completer);
|
|
|
+ }, () {
|
|
|
timer?.cancel();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
static CancelableFuture<T> retryWhen<T>(FutureCallback<T> callback,
|
|
|
int maxRetry, Duration interval, Predicate<dynamic> predicate) {
|
|
|
- Completer<T> completer = Completer<T>();
|
|
|
int retryCount = 0;
|
|
|
Timer? timer;
|
|
|
|
|
|
- void attempt() {
|
|
|
+ void attempt(Completer<T> completer) {
|
|
|
callback().then((value) {
|
|
|
if (!completer.isCompleted) {
|
|
|
completer.complete(value);
|
|
|
}
|
|
|
}).catchError((error) {
|
|
|
- if (retryCount < maxRetry && predicate(error)) {
|
|
|
+ if ((maxRetry <= 0 || retryCount < maxRetry) && predicate(error)) {
|
|
|
retryCount++;
|
|
|
- timer = Timer(interval, attempt);
|
|
|
+ timer = Timer(interval, () => attempt(completer));
|
|
|
} else {
|
|
|
if (!completer.isCompleted) {
|
|
|
completer.completeError(error);
|
|
|
@@ -65,9 +61,9 @@ class AsyncUtil {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- attempt();
|
|
|
-
|
|
|
- return CancelableFuture<T>(() {
|
|
|
+ return CancelableFuture<T>((completer) {
|
|
|
+ attempt(completer);
|
|
|
+ }, () {
|
|
|
timer?.cancel();
|
|
|
});
|
|
|
}
|
|
|
@@ -80,18 +76,22 @@ class AsyncUtil {
|
|
|
static CancelableFuture<T> delay<T>(
|
|
|
FutureCallback<T> callback, Duration interval) {
|
|
|
Timer? timer;
|
|
|
- return CancelableFuture<T>(
|
|
|
- () {
|
|
|
- timer?.cancel();
|
|
|
- },
|
|
|
- futureCompleter: (completer) {
|
|
|
- timer = Timer(interval, () {
|
|
|
- callback()
|
|
|
- .then(completer.complete)
|
|
|
- .catchError(completer.completeError);
|
|
|
+
|
|
|
+ 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();
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
///实际delay第一次执行的时间为delay+interval
|
|
|
@@ -100,9 +100,8 @@ class AsyncUtil {
|
|
|
Timer? timer;
|
|
|
Timer? delayTimer;
|
|
|
int counter = 0;
|
|
|
- Completer<T> completer = Completer<T>();
|
|
|
|
|
|
- void tick() {
|
|
|
+ void tick(Completer<T> completer) {
|
|
|
if (counter < times) {
|
|
|
callback().then((value) {
|
|
|
if (!completer.isCompleted) {
|
|
|
@@ -119,11 +118,11 @@ class AsyncUtil {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- delayTimer = Timer(delay, () {
|
|
|
- timer = Timer.periodic(interval, (Timer t) => tick());
|
|
|
- });
|
|
|
-
|
|
|
- return CancelableFuture<T>(() {
|
|
|
+ return CancelableFuture<T>((completer) {
|
|
|
+ delayTimer = Timer(delay, () {
|
|
|
+ timer = Timer.periodic(interval, (Timer t) => tick(completer));
|
|
|
+ });
|
|
|
+ }, () {
|
|
|
delayTimer?.cancel();
|
|
|
timer?.cancel();
|
|
|
});
|