如果第一个请求的响应代码是401,那么在Alamofire中有没有办法重新发送请求,我可以刷新令牌并再次重试我的请求?
问题是我已经使用MVVM和完成处理程序了。在我的ViewModel中,请求函数如下所示:
public func getProfile(completion: @escaping (User?) -> Void) {
guard let token = UserDefaults.standard.value(forKey: Constants.shared.tokenKey) else { return }
let headers = ["Authorization": "Bearer \(token)"]
URLCache.shared.removeAllCachedResponses()
Alamofire.request(Constants.shared.getProfile, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON { (response) in
switch response.result {
case .success:
guard let data = response.data else { return }
if JSON(data)["code"].intValue == 401 {
// here I need to refresh my token and re-send the request
} else {
let user = User(json: JSON(data)["data"])
completion(user)
}
completion(nil)
case .failure(let error):
print("Failure, ", error.localizedDescription)
completion(nil)
}
}
}
从我的ViewController我称之为:
viewModel.getProfile { (user) in
if let user = user {
...
}
}
所以我不知道如何在不使用新函数的情况下重试我的请求,所以我仍然可以从我的ViewController中的user
部分得到我的completion
响应。也许有人可以告诉我正确的道路。提前致谢!
如果收到401,你可以递归调用该函数吗?你肯定需要创建一些类型的退出条件,这样如果它继续失败它会爆发,但在我看来它会起作用。
是的,你可以在Alamofire 4.0上
RequestRetrier协议允许重试时遇到错误的请求。同时使用RequestAdapter和RequestRetrier协议时,您可以为OAuth1,OAuth2,Basic Auth甚至指数退避重试策略创建凭证刷新系统。可能性是无止境。以下是如何为OAuth2访问令牌实现刷新流程的示例。
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 {
refreshTokens { [weak self] succeeded, accessToken, refreshToken in
guard let strongSelf = self else { return }
strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }
if let accessToken = accessToken, let refreshToken = refreshToken {
strongSelf.accessToken = accessToken
strongSelf.refreshToken = refreshToken
}
strongSelf.requestsToRetry.forEach { $0(succeeded, 0.0) }
strongSelf.requestsToRetry.removeAll()
}
}
} else {
completion(false, 0.0)
}
}