优雅实现Ktor Client请求异常处理

代码

参考官方文档简单处理特殊 Status Code 响应错误,最简单的方式则是打印日志,当然可以根据自己的情况来包装。

private suspend fun ResponseException.debugLogging() {
    when (this) {
        is RedirectResponseException -> {
            // Status codes 3XX
            val errorString = response.body<String>()
            println("===== $errorString")
        }

        is ClientRequestException -> {
            // status codes 4XX
            println("===== status codes 4XX")
        }

        is ServerResponseException -> {
            // status codes 5XX
            println("===== status codes 5XX")
        }
    }
}

整合模板代码实现如下

internal suspend inline fun <reified T> HttpClient.doGetWithCatch(
    urlString: String,
    isThrows: Boolean = false,
    block: HttpRequestBuilder.() -> Unit = {}
): T? {
    return try {
        get(urlString, block).body<T>()
    } catch (exception: ResponseException) {
        exception.debugLogging()
        if (isThrows) throw exception else null
    } catch (ioException: IOException) {
        if (isThrows) throw ioException else null
    }
}

上面代码是适配get请求的,post一样,就不拷贝出来了。 加了一个参数isThrows作为是否将异常往上抛让调用者进行处理的标识。

使用

override suspend fun getCoinsMarkets(
    currency: String,
    page: Int,
    numCoinsPerPage: Int,
    order: String,
    includeSparkline7dData: Boolean,
    priceChangePercentageIntervals: String,
    coinIds: String?
): List<CoinGeckoMarketsDto> {
    return httpClient.doGetWithCatch<List<CoinGeckoMarketsDto>>("coins/markets") {
        parameter("vs_currency", currency)
        parameter("page", page)
        parameter("per_page", numCoinsPerPage)
        parameter("order", order)
        parameter("sparkline", includeSparkline7dData)
        parameter("price_change_percentage", priceChangePercentageIntervals)
        parameter("ids", coinIds)
    } ?: emptyList()
}

是不是看起来舒服多了?特别是在接口需要实现的方法多的时候,修改之后特有满足感