guard<T> static method

Future<AsyncValue<T>> guard<T>(
  1. Future<T> future()
)

Transforms a Future that may fail into something that is safe to read.

This is useful to avoid having to do a tedious try/catch. Instead of writing:

class MyNotifier extends AsyncNotifier<MyData> {
  @override
  Future<MyData> build() => Future.value(MyData());

  Future<void> sideEffect() async {
    state = const AsyncValue.loading();
    try {
      final response = await dio.get('my_api/data');
      final data = MyData.fromJson(response);
      state = AsyncValue.data(data);
    } catch (err, stack) {
      state = AsyncValue.error(err, stack);
    }
  }
}

We can use guard to simplify it:

class MyNotifier extends AsyncNotifier<MyData> {
  @override
  Future<MyData> build() => Future.value(MyData());

  Future<void> sideEffect() async {
    state = const AsyncValue.loading();
    // does the try/catch for us like previously
    state = await AsyncValue.guard(() async {
      final response = await dio.get('my_api/data');
      return Data.fromJson(response);
    });
  }
}

Implementation

static Future<AsyncValue<T>> guard<T>(Future<T> Function() future) async {
  try {
    return AsyncValue.data(await future());
  } catch (err, stack) {
    return AsyncValue.error(err, stack);
  }
}