ios - RequestRetrier Alamofire 锁不工作
问题描述
我正在使用 Alamofire 实现 RequestRetrier 来刷新给定用户的 accessToken。
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
lock.lock() ; defer { lock.unlock() }
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
requestsToRetry.append(completion)
if !isRefreshing {
refreshToken(completion: { [weak self] succeded, accessToken in
guard let strongSelf = self else { return }
strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }
strongSelf.requestsToRetry.forEach{ $0(succeded, 0.0) }
strongSelf.requestsToRetry.removeAll()
})
}
} else {
completion(false, 0.0)
}
}
何时strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }
调用它不会继续执行,所以我有一个无限循环。我尝试检查结果strongSelf.lock.try()
并返回 false。
当我使用错误的密码登录时会发生这种情况,因此服务器返回 401。
这是我的 refreshToken 代码
guard !isRefreshing else { return }
// ... Get user ... //
if let user = user {
isRefreshing = true
signIn(user: userDTO)
.subscribe(onNext: { [weak self] userSession in
guard let strongSelf = self else { return }
// ... Save accessToken ... //
completion(true, userSession.accessToken)
strongSelf.isRefreshing = false
}, onError: { [weak self] error in
guard let strongSelf = self else { return }
// ... Log out user ... //
completion(false, nil)
strongSelf.isRefreshing = false
})
.disposed(by: bag)
} else {
completion(false, nil)
}
解决方案
如 Github 问题https://github.com/Alamofire/Alamofire/issues/2544中所见,我可以通过更改来解决此问题:
private let lock = NSLock()
至
private let lock = NSRecursiveLock()
它们之间的区别在于,如果同一个线程正在尝试锁定,则可以解锁递归锁定。
推荐阅读
- r - 以前工作的包现在以“非零退出状态”解包
- python-3.x - 如何从 statsmodels 解释 ACF 和 PACF 函数?
- mongodb - 查询特定日期范围的 mongodb
- scala - 如何在地图中使用@unchecked 注释
- html - 将鼠标移向菜单本身时,下拉菜单消失
- python - 是否可以获得最后一次成功运行的时间?
- javascript - 使用表情符号回复时 Discord.js 执行功能
- r - 如果 case_when 找到某个结果,则停止执行
- android - 为什么新版 Google Play 管理中心网站不再使用“private_key.pepk”文件生成应用签名密钥?
- algorithm - 将简单的等距图像转换为 3D