【发布时间】:2019-09-12 12:08:40
【问题描述】:
我有一个应用程序,它通过后端进行身份验证并接收一个长期刷新令牌和短期访问令牌。我们使用访问令牌来授权我们的请求,并且每次它过期时,我们都会在使用新令牌重试 API 调用之前触发令牌更新(使用刷新令牌)。很标准的东西。
可以同时(异步)触发多个网络调用,但如果它们都有无效的访问令牌,我们只希望第一个通过并刷新令牌,而后续调用等待第一个调用完成之前继续。目前,我们是这样实现的:
private var renewingDeferred: Deferred<Unit>? = null
suspend fun renewTokens() {
coroutineScope {
if (renewingDeferred == null) {
renewingDeferred = async {
try {
tokens = tokensApi.renew().await()
} finally {
renewingDeferred = null
}
}
} else {
renewingDeferred?.await()
}
}
}
这个想法是每个具有无效访问令牌的请求都将调用renewTokens(),然后使用新的标头重试。 renewTokens() 的调用者不应该关心它是实际更新还是只是等待先前的更新完成,只要它知道一旦函数返回(不再暂停)令牌就会更新。据我所知,它运行良好,但我不完全确定代码,特别是 finally 块的 renewingDeferred = null 部分。
例如,假设请求 A 开始更新,请求 B 被触发并开始等待请求 A,然后 A 完成,将 renewingDeferred 设置为 null,但将该值设置为 null 会以某种方式影响请求 B 的等待状态?
另外,如果调用 API 时抛出异常怎么办?我没有 catch 块,有点假设 await()ing 在一个 deferred 上会以某种方式重新抛出,但协程中的异常处理并不是我的强项。很想在这方面得到一些建议。
另外,如果有人对如何以不同的方式解决这个问题有一个大致的了解,欢迎提出所有建议!
【问题讨论】: