Search code examples
riverpod

Asyncvalue guard Method inside build Riverpod


below is a code snippet from a tutorial I am trying to learn. appreciate if you could tell me why we are not using protection : asyncvalue.guard inside build() but later used when calling the same method?


@riverpod
class WeatherFirst extends _$WeatherFirst {
  @override
  FutureOr<String> build() {
    return _getTemp(Cities.seoul);
  }

  Future<String> _getTemp(Cities city) async {
    await Future.delayed(const Duration(seconds: 1));

    switch (city) {
      case Cities.seoul:
        return '${city.name} - 23';
      case Cities.london:
        throw 'Fail to fetch the temperature of ${city.name}';
      case Cities.bangkok:
        throw 'Fail to fetch the temperature of ${city.name}';
      case Cities.tokyo:
        return '${city.name} - 28';
    }
  }

  Future<void> getTemperature(Cities city) async {
    state = const AsyncLoading();

    state = await AsyncValue.guard(() => _getTemp(city));
  }
}

i tried inserting various error scenarios code works fine


Solution

  • This is the code of AsyncValue.guard

    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);
      }
    }
    

    all it is doing is to wrap your function in a try catch expression to save you few lines of code. if you are sure that _getTemp(city) cannot throw an error then you don't need to use guard at all. if you think that _getTemp(Cities.seoul) can throw an error, then you should return AsyncValue.guard(() => _getTemp(Cities.seoul)) in the build method.

    in the example that they provided, the city of seoul do not throw an error like london and bangkok, and thats the reason for not using the guard

    Edit

    I was incorrect in my answer: you should not put a guard in the build method. this is handled for you as its stated in the source code:

    /// If this method throws or returns a future that fails, the error
    /// will be caught and an [AsyncError] will be emitted.
    /// {@endtemplate}
    @visibleForOverriding
    FutureOr<State> build();