You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在同步Riverpod Provider中传递异常并捕获?

问题原因

你无法直接捕获UserNotSignedInException的核心原因是:Riverpod会将同步Provider抛出的异常自动包装为ProviderException,你的catch块只监听原始异常类型,自然无法命中。

解决方案

方案1:捕获ProviderException并检查内部异常类型

直接修改捕获逻辑,先捕获Riverpod的包装异常,再判断内部的真实异常类型:

try {
  ref.read(currentUserProvider);
  resolver.next();
} on ProviderException catch (e) {
  if (e.exception is UserNotSignedInException) {
    logger('User is not logged in, pushing intro route');
    router.push(const IntroRoute());
  } else {
    // 重新抛出非目标类型的异常,避免吞掉其他错误
    rethrow;
  }
}

方案2:避免在Provider内抛出异常(更推荐)

同步Provider抛出异常会让其进入错误状态,后续每次读取都需要处理异常逻辑,不如直接返回明确的状态值,代码更直观:

方式A:返回可选类型User?

修改Provider:

@Riverpod(dependencies: [firebaseAuth])
User? currentUser(CurrentUserRef ref) {
  return ref.watch(firebaseAuthProvider).currentUser;
}

读取时直接判断:

final user = ref.read(currentUserProvider);
if (user == null) {
  logger('User is not logged in, pushing intro route');
  router.push(const IntroRoute());
} else {
  resolver.next();
}

方式B:用密封类定义明确状态(可读性更强)

先定义状态密封类:

sealed class CurrentUserState {}
class LoggedIn extends CurrentUserState {
  final User user;
  LoggedIn(this.user);
}
class NotLoggedIn extends CurrentUserState {}

修改Provider返回状态类:

@Riverpod(dependencies: [firebaseAuth])
CurrentUserState currentUserState(CurrentUserStateRef ref) {
  final user = ref.watch(firebaseAuthProvider).currentUser;
  return user != null ? LoggedIn(user) : NotLoggedIn();
}

读取时通过switch处理不同状态:

switch (ref.read(currentUserStateProvider)) {
  case LoggedIn(:final user):
    resolver.next();
  case NotLoggedIn():
    logger('User is not logged in, pushing intro route');
    router.push(const IntroRoute());
}

内容的提问来源于stack exchange,提问作者Dario Digregorio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:25:15