mutateAsync method
Executes the mutation with params, returning the resolved data or rethrowing the caught error.
Useful when callers want standard try/catch error handling at the call site.
try {
final task = await createTodo.mutateAsync('New Task');
print('Created: ${task.id}');
} catch (e) {
print('Failed: $e');
}
Implementation
Future<T> mutateAsync(P params) async {
_status.value = MutationStatus.pending;
_error.value = null;
dynamic context;
T? autoPreviousSnapshot;
// 1. Automated Optimistic Update Snapshot & Application
if (optimisticKey != null) {
autoPreviousSnapshot = BloomData.getQueryData<T>(optimisticKey!);
if (optimisticData != null) {
BloomData.setQueryData<T>(
optimisticKey!,
(old) => optimisticData!(params, old) as T,
);
}
}
// 2. Custom onMutate hook
if (onMutate != null) {
try {
context = await onMutate!(params);
} catch (_) {
// Swallow onMutate errors — don't block the mutation
}
}
try {
final result = await mutateFn(params);
_data.value = result;
_status.value = MutationStatus.success;
_error.value = null;
// 3. Automated Cache Invalidation
for (final key in invalidateKeys) {
BloomData.invalidateQueries(key);
}
if (onSuccess != null) {
await onSuccess!(result, params, context);
}
if (onSettled != null) {
await onSettled!(result, null, params, context);
}
return result;
} catch (err) {
_error.value = err;
_status.value = MutationStatus.error;
// 4. Automated Optimistic Rollback
if (optimisticKey != null) {
BloomData.setQueryData<T>(
optimisticKey!, (_) => autoPreviousSnapshot as T);
}
if (onError != null) {
await onError!(err, params, context);
}
if (onSettled != null) {
await onSettled!(null, err, params, context);
}
rethrow;
}
}