guard<T> method Null safety

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:

    class MyNotifier extends StateNotifier<AsyncValue<MyData> {
      MyNotifier(): super(const AsyncValue.loading()) {
        _fetchData();
      }
    
      Future<void> _fetchData() 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);
        }
      }
    }
    

    which is redundant as the application grows and we need more and more of this pattern – we can use guard to simplify it:

    class MyNotifier extends StateNotifier<AsyncValue<MyData>> {
      MyNotifier(): super(const AsyncValue.loading()) {
        _fetchData();
      }
    
      Future<void> _fetchData() 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, stackTrace: stack);
      }
    }