在 StateNotifier 子类中使用 AsyncValue.guard 替代 try/catch

更新时间:2023-11-07 19:11

在编写自己的StateNotifier子类时,通常会使用try/catch块来处理可能失败的Futures:


class SignOutButtonController extends StateNotifier<AsyncValue> {
  SignOutButtonController({required this.authRepository})
      : super(const AsyncValue.data(null));
  final AuthRepository authRepository;
  Future<void> signOut() async {
    try {
      state = const AsyncValue.loading();
      await authRepository.signOut(); // this future can fail
      state = const AsyncValue.data(null);
    } catch (e) {
      state = AsyncValue.error(e);
    }
  }
}

在这种情况下,AsyncValue.guard 是一个方便的替代方法,它为我们处理了所有繁重的工作:


Future<void> signOut() async {
  state = const AsyncValue.loading();
  state = await AsyncValue.guard(() => authRepository.signOut());
}

以下是在 AsyncValue 类中实现此方法的方式:


abstract class AsyncValue<T> {
  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);
    }
  }
}