gpt4 book ai didi

ios - 使用 retryWhen 根据 http 错误代码更新 token

转载 作者:IT王子 更新时间:2023-10-29 05:17:21 25 4
gpt4 key购买 nike

我在 How to refresh oauth token using moya and rxswift 上找到了这个例子我不得不稍微改变一下才能编译。此代码对我的场景有效 80%。它的问题是它会针对所有 http 错误运行,而不仅仅是 401 错误。我想要的是将所有其他 http 错误作为错误传递,这样我就可以在其他地方处理它们,而不是在这里吞下它们。

使用这段代码,如果我得到 HttpStatus 500 ,它会运行3次验证码,这显然不是我想要的。

我试图更改此代码以仅处理句柄 401错误,但似乎无论我做什么我都无法编译代码。它总是提示错误的返回类型,"Cannot convert return expression of type Observable<Response> to return type Observable<Response>"这对我来说毫无意义..

我想要的:处理 401,但在出现所有其他错误时停止

import RxSwift
import KeychainAccess
import Moya

public extension ObservableType where E == Response {

/// Tries to refresh auth token on 401 errors and retry the request.
/// If the refresh fails, the signal errors.
public func retryWithAuthIfNeeded() -> Observable<E> {
return self.retryWhen {
(e: Observable<ErrorType>) in
return Observable.zip(e, Observable.range(start: 1, count: 3), resultSelector: { $1 })
.flatMap { i in
return AuthProvider.sharedInstance.request(
.LoginFacebookUser(
accessToken: AuthenticationManager.defaultInstance().getLoginTokenFromKeyChain(),
useFaceBookLogin: AuthenticationManager.defaultInstance().isFacebookLogin())
)
.filterSuccessfulStatusCodes()
.mapObject(Accesstoken.self)
.catchError {
error in
log.debug("ReAuth error: \(error)")
if case Error.StatusCode(let response) = error {
if response.statusCode == 401 {
// Force logout after failed attempt
log.debug("401:, force user logout")
NSNotificationCenter.defaultCenter().postNotificationName(Constants.Notifications.userNotAuthenticated, object: nil, userInfo: nil)
}
}
return Observable.error(error)
}.flatMapLatest({
token -> Observable<Accesstoken> in
AuthenticationManager.defaultInstance().storeServiceTokenInKeychain(token)
return Observable.just(token)
})
}
}
}
}

最佳答案

编译错误

哪一行有编译错误?在我看来,应该是这一行:

.catchError {
error in
//...
return Observable.error(error) // is this the line causing the compilation error?
}

如果是这样,可能是因为 catchError期望该 block 返回 Observable<Response>如果出现错误,它可以继续,而不是 Observable<ErrorType> .

无论哪种情况,它都有助于用更多类型注释您的代码,以便您可以查明此类问题,并帮助 Swift 编译器,而 Swift 编译器通常无法自行解决这些问题。所以像这样的事情会对你有所帮助:

.catchError {
error -> Observable<Response> in
//...
return Observable.error(error) // Swift should have a more accurate and helpful error message here now
}

请注意,我只是向您展示错误是什么以及如何让 Xcode 为您提供更好的错误消息。您尝试返回的内容仍然不正确。

仅在 401 上重试

我不确定您为什么期望此代码处理 401不同(除了发布到通知中心和日志记录)。实际上,您正在捕获错误,但您总是返回 ObservableError事件在最后 ( return Observable.error(error) ),所以它永远不会重试。

获取401要重试,您应该返回 Observable来自 retryWhen block ,它将发送 Next事件(表示您要重试)。对于所有其他状态代码,即 Observable应该发送 Error (正如您当前所做的那样),这将表示您不想重试,并且您希望传播错误。

所以像这样:

.retryWhen { errorObservable -> Observable<ErrorType> in
log.debug("ReAuth error: \(error)")
if case Error.StatusCode(let response) = error where response.statusCode == 401 {
log.debug("401:, force user logout")
NSNotificationCenter.defaultCenter().postNotificationName(Constants.Notifications.userNotAuthenticated, object: nil, userInfo: nil)
// If `401`, then return the `Observable<ErrorType>` which was given to us
// It will emit a `.Next<ErrorType>`
// Since it is a `.Next` event, `retryWhen` will retry.
return errorObservable
}
else {
// If not `401`, then `flatMap` the `Observable<ErrorType>` which
// is about to emit a `.Next<ErrorType>` into
// an `Observable<ErrorType>` which will instead emit a `.Error<ErrorType>`.
// Since it is an `.Error` event, `retryWhen` will *not* retry.
// Instead, it will propagate the error.
return errorObservable.flatMap { Observable.error($0) }
}
}

关于ios - 使用 retryWhen 根据 http 错误代码更新 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38281760/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com