Mayumi
Mayumi

Reputation: 11

How can I implement retryWhen using RxSwift and URLSessionTask?

I attempted to use the retryWhen function to renew my token, but unfortunately, it threw an error:

Value of type 'any Cancelable' has no member 'retryWhen'

task is URLSessionTask

return Observable.create { observer in
..........
            return Disposables.create {
                self.task?.cancel()
            }.retryWhen { error -> Observable<Error> in
                return error.flatMapLatest { error -> Observable<Error> in
                    return refreshToken()
                        .flatMapLatest { response -> Observable<Error> in
                            return Observable.error(ResponseErrorCode.FAILED)
                        }
                }
            }
}

Could you please guide me on how to fix it?

Upvotes: 1

Views: 91

Answers (1)

Daniel T.
Daniel T.

Reputation: 33979

You called the retry inside the Observable's create function. You should be calling retry on the observable, not while attempting to create it. There are also several other mistakes in this code. Many of which can be fixed by just using URLSession.shared.rx.response(request:) or URLSession.shared.rx.data(request:) from the RxCocoa library.

Also note that retryWhen() has been deprecated in favor of retry(when:).

return Observable.create { observer in
    //..........
    return Disposables.create {
        self.task?.cancel()
    }
}
.retry(when: { error -> Observable<Error> in
    return error.flatMapLatest { error -> Observable<Error> in
        return refreshToken()
            .flatMapLatest { response -> Observable<Error> in
                return Observable.error(ResponseErrorCode.FAILED)
            }
    }
})

Also, based on the body of the retry's closure, this will never retry because it will always emit an error. In order to retry, the Observable returned by the closure's body needs to emit a next event.

Also, why is the task in self? That should not be the case, but without seeing more of the code I'm not sure exactly what you are doing wrong there.

Rather than what you have, your code should look like this:

return urlSession.rx.data(request: urlRequest)
    .retry(when: { $0.flatMap { _ in refreshToken() } })

or

return URLSession.shared.rx.data(request: urlRequest)
    .retry(when: { $0.flatMap { _ in refreshToken() } })

I'm assuming refreshToken() returns an Observable that emits a single next event and then completes.)

Upvotes: 0

Related Questions