Recovery intercepts failures and runs a recovery action. It is intended for side effects such as logging, cleanup, or compensating work; by default the original error is rethrown.
Recovery link
What it is link
Recovery intercepts failures and runs a recovery action. It is intended for side effects such as logging, cleanup, or compensating work; by default the original error is rethrown.
When to use it link
- Cleaning up resources after a partial failure.
- Running an alternative workflow when the primary one fails.
- Transforming an error into a meaningful result with side effects.
Async / sync support link
| Wrapper | Support |
|---|
Func<R> | ✅ Async |
Func1<T, R> | ✅ Async |
Func2<T1, T2, R> | ✅ Async |
FuncSync<R> | ❌ No |
API reference link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // api-reference
// On Func<R>
Func<R> recover(RecoveryStrategy strategy);
// On Func1<T, R>
Func1<T, R> recover(RecoveryStrategy strategy);
// On Func2<T1, T2, R>
Func2<T1, T2, R> recover(RecoveryStrategy strategy);
class RecoveryStrategy {
const RecoveryStrategy({
required Future<void> Function(Object error) onError,
bool Function(Object error)? shouldRecover,
bool rethrowAfterRecovery = true,
});
}
|
Parameters link
| Parameter | Type | Description |
|---|
onError | Future<void> Function(Object error) | Side effect to run when an error occurs. |
shouldRecover | bool Function(Object error)? | Predicate deciding whether to run the recovery action. |
rethrowAfterRecovery | bool | Whether to rethrow the original error after the action (default true). |
Examples link
Basic example link
1
2
3
4
5
6
7
8
9
10
11
| final risky = Func<int>(() async => throw Exception('boom')).recover(
RecoveryStrategy(
onError: (error) async => print('recovered from $error'),
),
);
try {
await risky();
} catch (_) {
print('-1'); // recovery action ran before the original error was rethrown
}
|
Real-world example link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| final processPayment = Func1<Payment, Receipt>((payment) async {
return await primaryGateway.charge(payment) as Receipt;
}).recover(
RecoveryStrategy(
onError: (error) async => logger.warning(
'Primary gateway failed',
error,
),
shouldRecover: (error) => error is NetworkException,
),
);
// Usage
await processPayment(Payment()).catchError((_) => Receipt());
|
Best practices link
- Log the failure before recovering.
- Keep recovery paths simpler than the main path.
- Use
fallback when you only need a default value; use recover when you need logic.
Common pitfalls link
- Recovery masking errors: Make sure recovery failures are also handled or logged.
- Type mismatch: The recovery handler must return the same result type
R.