Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to retry the request with Moya/Combine #2323

Open
WoodyHang opened this issue Oct 10, 2023 · 1 comment
Open

How to retry the request with Moya/Combine #2323

WoodyHang opened this issue Oct 10, 2023 · 1 comment
Labels

Comments

@WoodyHang
Copy link

version: Moya/Combine (15.0.0), CombineExt (1.8.0)
Now I have a need to re -refresh the token when the token expires. After success, I need to re -execute the previous request again. The code is as follows:

private func request(_ target: Target) -> AnyPublisher<Moya.Response ,APIError> {
        let actualRequest = provider.requestPublisher(target)
        return actualRequest.tryMap { response in
            let json = try? response.mapJSON() as? [String: Any]
            if let json, let code = json["code"] as? String {
                if code == "ERR003" {
                    throw APIError.tokenExpired(reason: "token expired")
                }
                if code == "ERR004" {
                    throw APIError.refreshTokenExpired(reason: "login expired")
                }
            }
            return response
        }
        .mapError { error in
            if let error = error as? APIError {
                return error
            }
            if let error = error as? MoyaError {
                return APIError.moyaError(from: error)
            }
            return APIError.unknown
        }
        // `retryWhen` operator is provided by `CombineExt`
        .retryWhen { errorPublisher in
            return errorPublisher.filter { error in
                switch error {
                // When the error type is `tokenexpired`,Only go to re -request
                case .tokenExpired(_):
                    return true
                default: return false
                }
            }
            .setFailureType(to: APIError.self)
            .flatMap { error -> AnyPublisher<Void, APIError> in
                switch error {
                case .tokenExpired(_):
                    // This is my definition of re -refreshing token
                    return LogInManager.share.refreshToken()
                default:
                    return Just(()).setFailureType(to: APIError.self).mapToVoid().eraseToAnyPublisher()
                }
            }
        }
        .eraseToAnyPublisher()
       
    }

// The type of error I customized
enum APIError: Error, LocalizedError {
    case unknown, tokenExpired(reason: String), refreshTokenExpired(reason: String), moyaError(from: MoyaError)
    
    var errorDescription: String? {
        switch self {
        case .unknown:
            return "Unknown error"
        case .tokenExpired(let reason), .refreshTokenExpired(let reason):
            return reason
        case .moyaError(let from):
            return from.localizedDescription
        }
    }
}

However, after the success of the token, this code did not execute the original request. Does anyone know what happened in my code?

@peril-moya peril-moya bot added the question label Oct 10, 2023
@zhgchgli0718
Copy link

same question

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants