如何解决在多个异步协程中调用的方法如何只能被调用一次?
在主屏幕上,有3个异步请求:
viewModelScope.launch {
try {
val requestAccountDeffer = async { requestAccounts() }
val updateStatusDeffer = async { updateVerificationStatus() }
val requestProfileDeffer = async { requestProfile() }
requestAccountDeffer.await()
updateStatusDeffer.await()
requestProfileDeffer.await()
} catch (exception: Throwable) {
// ...
}
}
我的后端使用一个将过期一分钟的accessToken和一个updateToken来对其进行更新。在每个请求之前,都会检查accessToken是否已过期,并在必要时进行更新。
问题在于,如果accessToken在主屏幕开始处过期,则更新它的方法将被调用3次(在每个异步{...}块中),并且后端将在以下情况下返回错误:尝试更新accessToken。如何仅进行一次asynс块调用来更新令牌?
我可以在调用异步块之前同步更新令牌,但是在我看来,这不是完全正确的解决方案。
更新
当前accessToken和refreshToken存储在sharefPrefs中。
- 在开始进行改装请求之前,请检查令牌是否已过期。
- 如果它已过期,则调用Retrofit方法更新令牌,然后得到响应。
- 将新令牌保存在sharefPrefs中。
- 使用更新的访问令牌执行主请求。
解决方法
您可以通过使用Kotlin的异步Mutex
来避免同时更新共享资源(在这种情况下为访问令牌):
interface Mutex
(Mutex.kt
)协程互斥。
kotlinx-coroutines-core / kotlinx.coroutines.sync / Mutex
基本上,您可以锁定资源,必要时将其挂起,检查它是否已过期并可能更新,然后返回当前值。
private lateinit var currentToken: AccessToken
private val tokenMutex = Mutex()
suspend fun getToken(): AccessToken {
return tokenMutex.withLock {
if (currentToken.isExpired) {
// Refresh token
val newToken = ...
// Update the stored token
currentToken = newToken
newToken
} else currentToken
}
}
然后,而不是直接访问当前令牌值,而是使用此函数作为一种获取或更新代理。
Mutex
的功能与Lock
相同,除了它是挂起而不是阻塞并且是不可重入的。
也就是说,我认为在发出三个请求之前更新令牌的替代方法不会有什么问题。
旁注:绝对没有理由启动三个Deferred
工作并立即等待它们;这是coroutine scopes的非常好的用例:
coroutineScope {
launch { requestAccounts() }
launch { updateVerificationStatus() }
launch { requestProfile() }
}
此调用将暂停,直到所有新创建的作用域的子作业完成为止,并且一旦其中一个子项引发异常,该调用就会失败。
如果这种行为不是您想要的,则可以使用SupervisorScope
(另请参见When to use coroutineScope
vs supervisorScope
?),或安装自己的异常处理程序。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。