waitAllActions method

Future<void> waitAllActions(
  1. List<ReduxAction<St>>? actions, {
  2. bool completeImmediately = false,
  3. int? timeoutMillis,
})

Returns a future that completes when ALL given actions finish dispatching.

If completeImmediately is false (the default), this method will throw StoreException if none of the given actions are in progress when the method is called. Otherwise, the future will complete immediately and throw no error.

However, if you don't provide any actions (empty list or null), the future will complete when ALL current actions in progress finish dispatching. In other words, when no actions are currently in progress. In this case, if completeImmediately is false, the method will throw an error if no actions are in progress when the method is called.

Note: Waiting until no actions are in progress should only be done in test, never in production, as it's very easy to create a deadlock. However, waiting for specific actions to finish is safe in production, as long as you're waiting for actions you just dispatched.

You may also provide a timeoutMillis, which by default is 10 minutes. To disable the timeout, make it -1. If you want, you can modify defaultTimeoutMillis to change the default timeout.

Examples:

// Dispatches an actions that changes the state, then await for the state change:
expect(store.state.name, 'John')
dispatch(ChangeNameAction("Bill"));
var action = await store.waitCondition((state) => state.name == "Bill");
expect(action, isA<ChangeNameAction>());
expect(store.state.name, 'Bill');

// Dispatches actions and wait until no actions are in progress.
dispatch(BuyStock('IBM'));
dispatch(BuyStock('TSLA'));
await waitAllActions([]);
expect(state.stocks, ['IBM', 'TSLA']);

// Dispatches two actions in PARALLEL and wait for their TYPES:
expect(store.state.portfolio, ['TSLA']);
dispatch(BuyAction('IBM'));
dispatch(SellAction('TSLA'));
await store.waitAllActionTypes([BuyAction, SellAction]);
expect(store.state.portfolio, ['IBM']);

// Dispatches actions in PARALLEL and wait until no actions are in progress.
dispatch(BuyAction('IBM'));
dispatch(BuyAction('TSLA'));
await store.waitAllActions([]);
expect(store.state.portfolio.containsAll('IBM', 'TSLA'), isFalse);

// Dispatches two actions in PARALLEL and wait for them:
let action1 = BuyAction('IBM');
let action2 = SellAction('TSLA');
dispatch(action1);
dispatch(action2);
await store.waitAllActions([action1, action2]);
expect(store.state.portfolio.contains('IBM'), isTrue);
expect(store.state.portfolio.contains('TSLA'), isFalse);

// Dispatches two actions in SERIES and wait for them:
await dispatchAndWait(BuyAction('IBM'));
await dispatchAndWait(SellAction('TSLA'));
expect(store.state.portfolio.containsAll('IBM', 'TSLA'), isFalse);

// Wait until some action of a given type is dispatched.
dispatch(DoALotOfStuffAction());
var action = store.waitActionType(ChangeNameAction);
expect(action, isA<ChangeNameAction>());
expect(action.status.isCompleteOk, isTrue);
expect(store.state.name, 'Bill');

// Wait until some action of the given types is dispatched.
dispatch(ProcessStocksAction());
var action = store.waitAnyActionTypeFinishes([BuyAction, SellAction]);
expect(store.state.portfolio.contains('IBM'), isTrue);

See also: waitCondition - Waits until the state is in a given condition. waitActionCondition - Waits until the actions in progress meet a given condition. waitAllActions - Waits until the given actions are NOT in progress, or no actions are in progress. waitActionType - Waits until an action of a given type is NOT in progress. waitAllActionTypes - Waits until all actions of the given type are NOT in progress. waitAnyActionTypeFinishes - Waits until ANY action of the given types finish dispatching.

Implementation

Future<void> waitAllActions(
  List<ReduxAction<St>>? actions, {
  bool completeImmediately = false,
  int? timeoutMillis,
}) {
  if (actions == null || actions.isEmpty) {
    return this.waitActionCondition(
        completeImmediately: completeImmediately,
        completedErrorMessage: "No actions were in progress",
        timeoutMillis: timeoutMillis,
        (actions, triggerAction) => actions.isEmpty);
  } else {
    return this.waitActionCondition(
      completeImmediately: completeImmediately,
      completedErrorMessage: "None of the given actions were in progress",
      timeoutMillis: timeoutMillis,
      //
      (actionsInProgress, triggerAction) {
        for (var action in actions) {
          if (actionsInProgress.contains(action)) return false;
        }
        return true;
      },
    );
  }
}