AsyncReduxAction状态检查Skill asyncredux-action-status

这是一个用于Flutter应用中AsyncRedux库的技能,专门用于检查和操作Action的完成状态。通过ActionStatus对象,开发者可以获取Action执行的成功或失败信息、错误详情,并据此进行UI导航或单元测试。关键词包括AsyncRedux、Flutter、ActionStatus、状态管理、异步编程、错误处理、导航、测试。

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

名称: asyncredux-action-status 描述: 使用ActionStatus在dispatch返回后立即检查AsyncRedux(Flutter)action的完成状态。仅当需要知道action是否完成、是否因错误失败、产生什么错误,或如何基于成功或失败进行导航时使用。

AsyncRedux中的ActionStatus

ActionStatus对象提供有关action是否成功完成或遇到错误的信息。它由dispatchAndWait()和相关方法返回。

获取ActionStatus

使用dispatchAndWait()在action完成后获取状态:

var status = await dispatchAndWait(MyAction());

在action内部,也可以使用:

var status = await dispatchAndWait(SomeOtherAction());

ActionStatus属性

完成状态

  • isCompleted: 如果action已执行完成(无论成功或失败),返回true
  • isCompletedOk: 如果action在before()reduce()方法中没有错误完成,返回true
  • isCompletedFailed: 如果action遇到错误(与isCompletedOk相反),返回true

错误信息

  • originalError: before()reduce()方法最初抛出的错误,在任何修改之前
  • wrappedError: 经过action的wrapError()方法处理后的错误

执行跟踪

这些属性跟踪哪些生命周期方法已完成:

  • hasFinishedMethodBefore: 如果before()方法完成,返回true
  • hasFinishedMethodReduce: 如果reduce()方法完成,返回true
  • hasFinishedMethodAfter: 如果after()方法完成,返回true

注意:执行跟踪属性主要用于测试和调试。在生产代码中,专注于isCompletedOkisCompletedFailed

常见使用案例

成功后的条件导航

最常见的生产用途是在导航前检查action是否成功:

// 在widget回调中
Future<void> _onSavePressed() async {
  var status = await context.dispatchAndWait(SaveFormAction());
  if (status.isCompletedOk) {
    Navigator.pop(context);
  }
}

另一个带push导航的示例:

Future<void> _onLoginPressed() async {
  var status = await context.dispatchAndWait(LoginAction(
    email: emailController.text,
    password: passwordController.text,
  ));

  if (status.isCompletedOk) {
    Navigator.pushReplacementNamed(context, '/home');
  }
  // 如果失败,错误将通过UserExceptionDialog显示
}

测试Action错误

使用ActionStatus验证action是否抛出预期错误:

test('MyAction fails with invalid input', () async {
  var store = Store<AppState>(initialState: AppState.initial());

  var status = await store.dispatchAndWait(MyAction(value: -1));

  expect(status.isCompletedFailed, isTrue);
  expect(status.wrappedError, isA<UserException>());
  expect((status.wrappedError as UserException).msg, "Value must be positive");
});

测试Action成功

test('SaveAction completes successfully', () async {
  var store = Store<AppState>(initialState: AppState.initial());

  var status = await store.dispatchAndWait(SaveAction(data: validData));

  expect(status.isCompletedOk, isTrue);
  expect(store.state.saved, isTrue);
});

检查原始错误与包装后错误

当您的action使用wrapError()转换错误时,可以检查两者:

class MyAction extends AppAction {
  @override
  Future<AppState?> reduce() async {
    throw Exception('Network error');
  }

  @override
  Object? wrapError(Object error, StackTrace stackTrace) {
    return UserException('Could not save. Please try again.');
  }
}

// 在测试中:
var status = await store.dispatchAndWait(MyAction());
expect(status.originalError, isA<Exception>()); // 原始Exception
expect(status.wrappedError, isA<UserException>()); // 包装后的UserException

Action生命周期与状态

action生命周期按此顺序运行:

  1. before() - 首先运行,可用于前置条件
  2. reduce() - 其次运行(仅当before()成功)
  3. after() - 最后运行,始终执行(像finally块)

isCompletedOk属性仅当before()reduce()都没有错误完成时为true。注意,after()中的错误不影响isCompletedOk

如果before()抛出错误,reduce()不会运行,但after()仍会执行。

最佳实践

  1. 使用状态更改进行UI更新: 在生产中,更倾向于检查状态更改而不是action状态。保留ActionStatus用于需要基于成功/失败执行副作用(如导航)的情况。

  2. 使用isCompletedOk进行导航: 常见模式是在action成功后导航:

    if (status.isCompletedOk) Navigator.pop(context);
    
  3. 在测试中使用wrappedError: 当测试错误处理时,检查wrappedError以查看用户实际将看到的内容(经过wrapError()处理后)。

  4. 使用originalError进行调试: 当需要查看任何转换前的底层错误时,使用originalError

参考

文档中的URL: