guard method

Future<void> guard(
  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 loading and 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().copyWithPrevious(state);
    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 {
    // does the loading and try/catch for us like previously
    await guard(() async {
      final response = await dio.get('my_api/data');
      return Data.fromJson(response);
    });
  }
}

Implementation

Future<void> guard(Future<T> Function() future) async {
  state = AsyncValue<T>.loading().copyWithPrevious(state);
  try {
    state = AsyncValue.data(await future());
  } catch (err, stack) {
    state = AsyncValue.error(err, stack);
  }
}