Kotlin中在exchangeToFlow内调用createExceptionAndAwait()的最佳方式
WebFlux中exchangeToFlow内调用挂起函数createExceptionAndAwait()的正确实现
你的核心问题是:exchangeToFlow的lambda并非挂起函数,直接在里面调用挂起函数createExceptionAndAwait()会编译失败——因为挂起函数只能在挂起上下文或其他挂起函数中调用。下面是几种最佳实现方式:
方案一:用flow构建异常流
最直观的方式是在非2xx状态时,通过flow构建一个仅抛出异常的流,把挂起函数调用放到flow的挂起上下文里:
return webClient.post() .uri(url) .bodyValue(body) .accept(APPLICATION_JSON) .exchangeToFlow { clientResponse -> if (clientResponse.statusCode().is2xxSuccessful) { clientResponse.bodyToFlow() } else { flow { val exception = clientResponse.createExceptionAndAwait() throw httpExceptionHandlerUtil.handleException(exception) } } }
方案二:用onStart提前检查状态
利用onStart操作符的挂起上下文,在流开始前完成状态检查和异常处理,代码更简洁:
return webClient.post() .uri(url) .bodyValue(body) .accept(APPLICATION_JSON) .exchangeToFlow { clientResponse -> clientResponse.bodyToFlow() .onStart { if (!clientResponse.statusCode().is2xxSuccessful) { val exception = clientResponse.createExceptionAndAwait() throw httpExceptionHandlerUtil.handleException(exception) } } }
方案三:用transform操作符统一处理
transform操作符支持挂起上下文,你可以在里面完成状态判断、异常处理和流发射的逻辑:
return webClient.post() .uri(url) .bodyValue(body) .accept(APPLICATION_JSON) .exchangeToFlow { clientResponse -> transform { if (!clientResponse.statusCode().is2xxSuccessful) { val exception = clientResponse.createExceptionAndAwait() throw httpExceptionHandlerUtil.handleException(exception) } emitAll(clientResponse.bodyToFlow()) } }
关键说明
- 所有方案的核心都是把挂起函数
createExceptionAndAwait()的调用放到支持挂起上下文的Flow操作符或构建块中,避免在非挂起的lambda直接调用。 - 不要直接在
exchangeToFlow的根lambda里throw异常,通过Flow的错误信号传递异常更符合Reactive Streams的规范,也能保证流的异常处理链路正常工作。
内容的提问来源于stack exchange,提问作者rjma30
相关产品推荐
相关产品推荐

