如何使用Java Vavr Future异步执行多返回类型REST调用并获取全部结果
解决方案
你遇到的核心问题是直接用Future.sequence合并不同泛型的Future会丢失类型信息,针对你只有4-5个固定异步任务的场景,最优方案是不强制合并成统一泛型集合,等待所有任务完成后分别取结果,完全可以保留每个返回值的类型信息:
方案1:分别获取结果(类型安全,推荐)
你用的工具类大概率是Vavr,示例代码如下:
// 1. 先启动所有异步任务,任务会立刻后台执行,不会阻塞 Future<Either<ViolationException, Products>> productsFuture = Future.of(() -> validateProducts(input)); Future<Either<DomainException, List<Category>>> categoriesFuture = Future.of(() -> validateCategory(input)); // 其他2-3个任务按照同样方式定义即可 // 2. 等待所有任务执行完成,无论成功失败都会进入完成状态 Future.sequence(List.of(productsFuture, categoriesFuture, otherFuture1, otherFuture2)).await(); // 3. 分别获取每个任务的结果,完全保留原有泛型类型,不需要类型转换 Either<ViolationException, Products> productsResult = productsFuture.get(); Either<DomainException, List<Category>> categoriesResult = categoriesFuture.get(); // 其他任务结果同理获取
如果你用的是JDK原生CompletableFuture,写法逻辑一致:
// 启动所有任务 CompletableFuture<Either<ViolationException, Products>> productsFuture = CompletableFuture.supplyAsync(() -> validateProducts(input)); CompletableFuture<Either<DomainException, List<Category>>> categoriesFuture = CompletableFuture.supplyAsync(() -> validateCategory(input)); // 等待所有任务执行完成 CompletableFuture.allOf(productsFuture, categoriesFuture, otherFuture1, otherFuture2).join(); // 分别取结果 Either<ViolationException, Products> productsResult = productsFuture.join(); Either<DomainException, List<Category>> categoriesResult = categoriesFuture.join();
方案2:统一封装结果集合
如果你确实需要把所有结果放到同一个集合中统一遍历处理,可以定义统一的结果封装类,避免通配符导致的类型丢失:
// 定义统一的结果父接口,用sealed限制实现类范围 sealed interface AsyncResult permits ProductsResult, CategoriesResult, OtherResult {} // 每个返回类型对应一个封装实现 record ProductsResult(Either<ViolationException, Products> result) implements AsyncResult {} record CategoriesResult(Either<DomainException, List<Category>> result) implements AsyncResult {} record OtherResult(Either<DomainException, OtherModel> result) implements AsyncResult {} // 启动任务时直接封装为统一类型 Future<AsyncResult> productsFuture = Future.of(() -> new ProductsResult(validateProducts(input))); Future<AsyncResult> categoriesFuture = Future.of(() -> new CategoriesResult(validateCategory(input))); // 合并后得到类型明确的结果集合 Future<Seq<AsyncResult>> allResultFuture = Future.sequence(List.of(productsFuture, categoriesFuture)); // 后续处理可用模式匹配区分类型 allResultFuture.get().forEach(result -> { if (result instanceof ProductsResult pr) { // 处理商品结果 } else if (result instanceof CategoriesResult cr) { // 处理分类结果 } });
两种方案都可以保证所有任务无论成功失败执行完成后,你能拿到每一个调用的完整返回结果。
内容的提问来源于stack exchange,提问作者raaeusagvc
相关产品推荐
相关产品推荐

