处理 API 响应的错误和异常

问题描述 投票:0回答:1

我正在寻找更好的方法来处理错误和异常。

我想捕获异常并将其传递回该函数的调用者。但方法签名是

<LoginResponseDto, ErrorResponseDto>
ErrorResponseDto 是当 API 返回状态代码错误时我将返回的模型。但是,可能会引发异常,我也想将其冒泡给调用者。

我不确定我当前的实现是否可行。

处理此类事情的最佳方法是什么

   override suspend fun loginUser(loginRequestModel: LoginRequestModel): APIResponse<LoginResponseDto, ErrorResponseDto> {
            return try {
                val response = httpClient
                    .post("https://endpoint") {
                        contentType(ContentType.Application.Json)
    
                        setBody(
                            LoginRequestDto(
                               /* body data */
                            )
                        )
                    }
    
                if (response.status.value == 200) {
                    APIResponse.OnSuccess(response.body())
                }
                else {
                    APIResponse.OnFailure(response.body())
                }
            }
            catch (exception: Exception) {
                if (exception is CancellationException) {
                    Timber.e(exception)
                    throw exception
                }
                else {
                    Timber.e(exception)
                    // This works as I am still return the ErrorResponseDto but looks hacky doing it like this
                    APIResponse.OnFailure(ErrorResponseDto(
                        errors = listOf(
                            ErrorDto(
                                code = exception.localizedMessage ?: "",
                                detail = exception.message ?: "Unknown"))))

                    // But what I would want to do is this
                    // APIResponse.OnFailure(exception) 
                }
            }
        }
    
       interface APIResponse<out T, out E> {
            data class OnSuccess<T>(val data: T) : APIResponse<T, Nothing>
            data class OnFailure<E>(val error: E) : APIResponse<Nothing, E>
        }
    
        data class ErrorResponseDto(
            val errors: List<ErrorDto>
        )
    
        data class ErrorDto(
            val code: String,
            val detail: String
        )
android kotlin error-handling ktor
1个回答
0
投票

我个人将客户端设置为期望成功,然后使用封装所有错误的

kotlin.Result
而不是返回奇怪的类型接口。

唯一要记住的是,当 http 调用本身是失败的原因时,Ktor 会给我们

ResponseException

override suspend fun loginUser(loginRequestModel: LoginRequestModel): Result<LoginResponseDto> = 
    runCatching {
        // note that client is set up to expect failure so it will throw when response code is not 200
        httpClient
            .post("https://endpoint") {
                contentType(ContentType.Application.Json)

                setBody(
                    LoginRequestDto(
                       /* body data */
                    )
                )
            }.body()
    }.onFailure {
        // bubble up cancellation
        if (it is CancellationException) throw it
    }

现在在呼叫站点中剩下的就是:

api.loginUser(loginModel).fold (
    onSuccess = { loginDto -> handleSuccessfullLogin(loginDto) },
    onFailure = { error ->
        when (error) {
            is ResponseException -> { // http call failed here
                error.response.status // returned code and message is here
            }
            else -> { // other causes  }
        }
    }
)

注意

ResponseException
如何包含完整的
HttpResonse
,这意味着如果需要的话我们也可以尝试获取错误
.body()

© www.soinside.com 2019 - 2024. All rights reserved.