如何移除Java代码中的CompletableFuture将异步转为同步并处理响应错误
关于CompletableFuture异步逻辑改同步的改造方案
一、不能直接删除futures.add(CompletableFuture.supplyAsync(()部分
核心原因有两点:
- 原方法依赖
List<CompletableFuture<String>>类型的入参收集异步任务结果,改成同步后该入参完全无用,方法签名需要先调整 - 原逻辑里
supplyAsync包裹的异步执行逻辑、handle绑定的结果/异常处理逻辑是绑定在一起的,直接删除会导致业务逻辑断裂
二、具体改造步骤
第一步:修改方法签名
删除无用的futures入参,根据业务需要选择返回处理后的结果集合,或者保持无返回:
// 示例方法签名,可根据实际需求调整返回值 private List<String> getClockRequestList(String createdBy, String capacityType, ResourceHierarchy rA, int[] clock_ids, Boolean checkIfCreatingClock, String url) throws JsonProcessingException { List<String> resultList = new ArrayList<>(); // 改造后的业务逻辑放在这里 return resultList; }
第二步:异步逻辑转同步执行
把supplyAsync包裹的HTTP调用逻辑直接拿出顺序执行,handle内的结果处理逻辑直接跟在HTTP调用后面即可,不需要再包CompletableFuture:
for (int clockid : clock_ids) { String clockRequest = requestMapperImpl.getClockRequest(createdBy, capacityType, String.valueOf(clockid), rA, checkIfCreatingClock); String response = null; Throwable error = null; // 同步执行HTTP请求,移除异步包裹 try { response = genericRestClientImp.httpPostData(clockRequest, url); logger.info("Response from EAM is: {}",response); } catch (IOException e) { logger.error(e); error = e; } // 原handle内的结果处理逻辑完全复用 String handleResult; if (response != null && error == null) { if (checkIfCreatingClock) { if (response.contains(AppConstant.FAILURE_MSG)) { logger.info(responseMapperImpl.responseMessageClock(AppConstant.FAILURE, response, rA, clockid)); handleResult = responseMapperImpl.responseMessageClock(AppConstant.FAILURE, response, rA, clockid); } else if (response.contains(AppConstant.STATUS_404)) { logger.info(responseMapperImpl.responseMessageClock(AppConstant.STATUS_404, response, rA, clockid)); handleResult = responseMapperImpl.responseMessageClock(AppConstant.STATUS_404, response, rA, clockid); } else if (response.contains(AppConstant.SUCCESS_MSG)) { logger.info(responseMapperImpl.responseMessageClock(AppConstant.SUCCESS, response, rA, clockid)); handleResult = responseMapperImpl.responseMessageClock(AppConstant.SUCCESS, response, rA, clockid); } else { logger.info(responseMapperImpl.responseMessageClock(AppConstant.ERROR, response, rA, clockid)); handleResult = responseMapperImpl.responseMessageClock(AppConstant.ERROR, response, rA, clockid); } } else { if (response.contains(AppConstant.SUCCESS) || response.contains(StringUtils.capitalize(AppConstant.SUCCESS))) { logger.info(responseMapperImpl.responseMessageTotalCapacity(AppConstant.SUCCESS, response, rA, clockid)); handleResult = responseMapperImpl.responseMessageTotalCapacity(AppConstant.SUCCESS, response, rA, clockid); } else if (response.contains(AppConstant.FAILURE) || response.contains(StringUtils.capitalize(AppConstant.FAILURE))) { logger.info(responseMapperImpl.responseMessageTotalCapacity(AppConstant.FAILURE, response, rA, clockid)); handleResult = responseMapperImpl.responseMessageTotalCapacity(AppConstant.FAILURE, response, rA, clockid); } else { logger.info(responseMapperImpl.responseMessageTotalCapacity(AppConstant.ERROR, response, rA, clockid)); handleResult = responseMapperImpl.responseMessageTotalCapacity(AppConstant.ERROR, response, rA, clockid); } } } else { ErrorResponse errorResponse = new ErrorResponse(); ResponseStatusMsg responseStatusMsg = new ResponseStatusMsg(); responseStatusMsg.setStatusCode(HttpStatus.NOT_FOUND.value()); errorResponse.setClockId(clockid); errorResponse.setResourceId(rA.getResourceID()); responseStatusMsg.setError("Failure in getting response from the "+url); errorResponse.setResponse(responseStatusMsg); List<ErrorResponse> errorList = new ArrayList(); errorList.add(errorResponse); responseObject.setError(errorList); logger.info(responseObject.toString()); handleResult = responseObject.toString(); } // 用结果集合代替原future集合收集处理后的返回值 resultList.add(handleResult); }
三、响应和错误处理注意事项
- 原异步场景下
handle的正常返回、异常捕获逻辑可以100%复用,不需要调整判断规则 - 原异步逻辑中为了把异常传递给
handle抛出的RuntimeException可以删掉,同步场景下直接把异常赋值给error变量即可,避免打断整个循环 - 如果业务不需要保留所有处理后的结果,也可以删掉
resultList相关逻辑,保持方法无返回即可
内容的提问来源于stack exchange,提问作者Jeevan Gyawali
相关产品推荐
相关产品推荐

