AsyncRedux中止调度Skill asyncredux-abort-dispatch

这个技能用于在AsyncRedux(Flutter状态管理库)中通过abortDispatch()方法条件性地阻止Redux动作的执行。它允许在动作生命周期前检查条件,如用户认证、角色授权、功能启用状态、数据新鲜度或维护模式,以静默跳过动作,不执行before()、reduce()和after()方法,保持状态不变。适用于实现安全守卫、功能标志、性能优化和条件调度等场景,提升应用的安全性和效率。关键词:AsyncRedux, Flutter, 动作中止, 条件调度, 状态管理, 认证授权, 功能标志, 维护模式, 静默跳过。

移动开发 0 次安装 0 次浏览 更新于 3/19/2026

名称: asyncredux-abort-dispatch 描述: 停止AsyncRedux(Flutter)动作的调度。仅在用户提到abortDispatch(),或明确要求在特定条件下中止或阻止调度时使用。

AsyncRedux 中止调度

什么是abortDispatch()?

abortDispatch()方法是ReduxAction上的一个可选方法,允许您条件性地防止动作执行。当此方法返回true时,整个动作将被跳过——before()reduce()after()不会运行,状态保持不变。

class MyAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() {
    // 返回true以中止,false以继续
    return someCondition;
  }

  @override
  AppState? reduce() {
    // 仅当abortDispatch()返回false时运行
    return state.copy(/* ... */);
  }
}

基本用法

最简单的用例是在允许动作继续之前检查条件:

class LoadUserProfile extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user == null;

  @override
  Future<AppState?> reduce() async {
    // 仅当用户已登录时运行
    final profile = await api.fetchProfile(state.user!.id);
    return state.copy(profile: profile);
  }
}

使用abortDispatch()的动作生命周期

abortDispatch()返回true时,整个动作生命周期将被跳过:

class MyAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.shouldSkip;  // 如果为true:

  @override
  void before() {
    // 中止时不调用
  }

  @override
  AppState? reduce() {
    // 中止时不调用
  }

  @override
  void after() {
    // 中止时不调用
  }
}

这与在before()中抛出错误不同,后者仍会导致after()运行。

认证守卫模式

一个常见模式是创建一个需要认证的基动作:

/// 需要认证用户的基动作
abstract class AuthenticatedAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user == null;
}

/// 扩展此类的动作仅在用户登录时运行
class FetchUserOrders extends AuthenticatedAction {
  @override
  Future<AppState?> reduce() async {
    // 安全使用state.user! - abortDispatch确保其不为null
    final orders = await api.getOrders(state.user!.id);
    return state.copy(orders: orders);
  }
}

class UpdateUserSettings extends AuthenticatedAction {
  final Settings newSettings;
  UpdateUserSettings(this.newSettings);

  @override
  Future<AppState?> reduce() async {
    await api.updateSettings(state.user!.id, newSettings);
    return state.copy(settings: newSettings);
  }
}

创建带有中止逻辑的基动作

您可以在基动作中组合多个中止条件:

abstract class AppAction extends ReduxAction<AppState> {
  // 在子类中重写以添加动作特定的中止逻辑
  bool shouldAbort() => false;

  @override
  bool abortDispatch() {
    // 全局中止条件
    if (state.isMaintenanceMode) return true;
    if (state.isAppLocked) return true;

    // 动作特定的中止条件
    return shouldAbort();
  }
}

class RefreshData extends AppAction {
  @override
  bool shouldAbort() {
    // 如果数据仍新鲜,则不刷新
    return state.lastRefresh != null &&
        DateTime.now().difference(state.lastRefresh!) < Duration(minutes: 5);
  }

  @override
  Future<AppState?> reduce() async {
    final data = await api.fetchData();
    return state.copy(data: data, lastRefresh: DateTime.now());
  }
}

基于角色的授权

使用abortDispatch()实现基于角色的访问控制:

abstract class AdminAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user?.role != UserRole.admin;
}

class DeleteAllUsers extends AdminAction {
  @override
  Future<AppState?> reduce() async {
    // 仅管理员可以执行此代码
    await api.deleteAllUsers();
    return state.copy(users: []);
  }
}

条件功能动作

当功能被禁用时阻止动作:

class UsePremiumFeature extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => !state.user!.isPremium;

  @override
  AppState? reduce() {
    // 仅限高级用户的功能
    return state.copy(/* ... */);
  }
}

内置混合:AbortWhenNoInternet

AsyncRedux提供AbortWhenNoInternet,一个混合,当没有互联网连接时静默中止动作:

class FetchLatestNews extends AppAction with AbortWhenNoInternet {
  @override
  Future<AppState?> reduce() async {
    // 仅当互联网可用时运行
    final news = await api.fetchNews();
    return state.copy(news: news);
  }
}

AbortWhenNoInternet的关键特性:

  • 不显示错误对话框
  • 不抛出异常
  • 动作被静默取消
  • 仅检查设备互联网开关状态(不检查服务器可用性)

CheckInternet相比,后者显示错误对话框而不是静默中止。

abortDispatch() 与在before()中抛出异常

根据用例选择正确方法:

方法 after()运行? 显示错误? 何时使用
abortDispatch()返回true 静默跳过动作
before()中抛出异常 是(如果是UserException) 向用户显示错误
// 静默中止 - 用户不知道动作被跳过
class SilentRefresh extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.isOffline;
  // ...
}

// 可见错误 - 用户看到消息
class ExplicitRefresh extends ReduxAction<AppState> {
  @override
  void before() {
    if (state.isOffline) {
      throw UserException('离线时无法刷新');
    }
  }
  // ...
}

何时使用abortDispatch()

好的使用场景:

  • 认证守卫(动作需要登录用户)
  • 授权检查(动作需要特定角色/权限)
  • 功能标志(仅限高级用户)
  • 新鲜度检查(如果数据最近,则不重新获取)
  • 维护模式(全局禁用某些动作)
  • 幂等性(如果动作效果已应用,则跳过)

考虑替代方案时:

  • 您希望用户看到错误消息(在before()中抛出UserException
  • 需要运行清理代码(使用before() + after()模式)
  • 实现速率限制(使用ThrottleDebounce混合)
  • 防止重复调度(使用NonReentrant混合)

完整示例

// 带有常见中止逻辑的基动作
abstract class AppAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() {
    // 全局维护模式检查
    if (state.maintenanceMode) return true;
    return false;
  }
}

// 认证动作,同时检查维护模式
abstract class AuthenticatedAction extends AppAction {
  @override
  bool abortDispatch() {
    // 首先检查父条件
    if (super.abortDispatch()) return true;
    // 然后检查认证
    return state.currentUser == null;
  }
}

// 管理员动作,带有完整授权链
abstract class AdminAction extends AuthenticatedAction {
  @override
  bool abortDispatch() {
    if (super.abortDispatch()) return true;
    return state.currentUser?.role != UserRole.admin;
  }
}

// 使用层次结构的具体动作
class BanUser extends AdminAction {
  final String userId;
  BanUser(this.userId);

  @override
  Future<AppState?> reduce() async {
    // 仅当以下条件满足时才到达这里:
    // 1. 不在维护模式
    // 2. 用户已登录
    // 3. 用户是管理员
    await api.banUser(userId);
    return state.copy(
      users: state.users.where((u) => u.id != userId).toList(),
    );
  }
}

重要注意事项

  • abortDispatch()before()reduce()after()之前检查
  • 中止时,不会发生状态更改
  • 动作被静默跳过——默认不抛出或记录错误
  • 谨慎使用此功能;文档警告它是一个“强大功能”,仅当您“确定它是正确解决方案”时才使用

参考文献

文档URL: