zipRequest function

Future<ZipResults> zipRequest(
  1. List<ZipRequest> requests, {
  2. bool eagerError = true,
  3. CancelToken? cancelToken,
  4. Duration? timeout,
})

Main function to execute multiple callback-based requests concurrently.

Returns a Future that completes when all requests finish. Total execution time equals the longest individual request.

Parameters:

  • requests: List of ZipRequest instances to execute
  • eagerError: If true, fail immediately on first error (default: true)
  • cancelToken: Optional token to cancel all requests
  • timeout: Optional timeout duration for all requests (not per-request timeout)

Returns: ZipResults containing all results

Example:

final results = await zipRequest([
  ZipRequest<UserInfo>(request: getUserAsync, tag: 'user'),
  ZipRequest<List<Product>>(request: getProductsAsync, tag: 'products'),
], timeout: Duration(seconds: 30));

final user = results.getRequestByTag<UserInfo>('user');
final products = results.getRequestByTag<List<Product>>('products');

Implementation

Future<ZipResults> zipRequest(
  List<ZipRequest> requests, {
  bool eagerError = true,
  CancelToken? cancelToken,
  Duration? timeout,
}) async {
  //  Validation Phase
  final tagIndexMap = _validateAndBuildTagMap(requests);

  //  Initialization Phase
  final states = _initializeRequestStates(requests);
  _registerCancellation(cancelToken, states);

  //  Execution Phase
  _executeRequests(states);

  // Waiting Phase
  Future<ZipResults> executeFuture() async {
    if (eagerError) {
      // Eager error mode: throw on first error
      final results = await _waitWithEagerError(states);

      // Result Aggregation Phase
      return ZipResults(results, tagIndexMap);
    } else {
      // Partial success mode: collect all results and errors
      final (results, errors) = await _waitWithPartialSuccess(states);

      // Result Aggregation Phase
      return ZipResults(results, tagIndexMap, errors);
    }
  }

  // Apply timeout if specified
  if (timeout != null) {
    return executeFuture().timeout(
      timeout,
      onTimeout: () {
        // Cancel all pending requests on timeout
        for (final state in states) {
          if (!state.isCompleted) {
            state.completer.completeError(
              TimeoutException(
                'ZipRequest timed out after ${timeout.inSeconds} seconds',
                timeout,
              ),
            );
          }
        }
        throw TimeoutException(
          'ZipRequest timed out after ${timeout.inSeconds} seconds',
          timeout,
        );
      },
    );
  }

  return executeFuture();
}