我有一个应用程序,该应用程序通过后端进行身份验证,并收到一个长期的刷新令牌和一个短暂的访问令牌。我们使用访问令牌来授权请求,并且每次过期时,我们都会触发令牌更新(使用刷新令牌),然后使用新令牌重试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()
的调用者知道函数一旦返回(即不再挂起)就更新令牌,它就不必关心它实际上是更新还是只是等待先前的更新完成。据我所知,它可以正常工作,但是我不确定代码,特别是renewingDeferred = null
块的finally
部分。
例如,假设请求A开始更新,请求B被触发并开始等待请求A,然后A完成,将renewingDeferred
设置为null
,但确实将该值设置为null
会以某种方式影响请求B的等待状态吗?
此外,如果在调用API时抛出异常怎么办?我没有catch
块,有点假设await()
在延迟的抛出上会以某种方式重新抛出,但是协程中的异常处理并不是我的强项。希望就此获得一些建议。
此外,如果有人对应该如何以其他方式解决此问题有一个一般的想法,欢迎提出所有建议!
答案 0 :(得分:0)
您可以使用Mutex解决此问题。 创建一个用于协程锁定的属性,并在调用renewToken时锁定Mutex,直到令牌更新为止。