I am trying to add a check against the response status code in the event my remote service returns a 401.
I have am trying to use the PromiseKit URLSession extension.
Imagine I have something basic such as
return firstly {
URLSession.shared.dataTask(.promise, with: request)
}.compactMap {
try JSONDecoder().decode(T.self, from: $0.data)
}
What I would like to do is add a check against the response state code, so I may throw an error and execute some further steps.
Something like
return firstly {
URLSession.shared.dataTask(.promise, with: request)
}.map { session in
if (session.response as? HTTPURLResponse)?.statusCode == 401 {
// throw a custom error here
// something like
// throw TokenProviderError.unauthorized
}
return session.data
}.compactMap {
try JSONDecoder().decode(T.self, from: $0)
}.catch { error in
// check the error thrown here and do something
}
This has an exception
Cannot convert return expression of type 'PMKFinalizer' to return type 'Promise'
Is it possible to introduce something like retryWhen which will allow me to catch an errors and check?
I was trying to achieve exactly the same thing as you did, I think the retrywhen feature you were looking for is called recover, you can find it in GitHub PromiseKit Document
return firstly {
URLSession.shared.dataTask(.promise, with: request)
}.map { session in
if (session.response as? HTTPURLResponse)?.statusCode == 401 {
throw TokenProviderError.unauthorized
}
return session.data
}.compactMap {
try JSONDecoder().decode(T.self, from: $0)
}
// above is a copy of your code
.recover { error in // instead of .catch, use .recover here
guard let err = error as? TokenProviderError,
err == .unauthorized
else { throw error } // we only care 401 error here, other error will be handled in caller's .catch
// in my case, the reason for 401 error is due to an expired access token, so I will try to use refresh token to get a valid access token and make the same request again
return firstly {
loginWithRefreshToken(token: myRefreshToken)
}.then { loginRes -> Promise<(data: Data, response: URLResponse)> in
// loginRes contains new access token, set it to request "Authorization" header, and make the same request again
request.setValue(loginRes.accessToken, forHTTPHeaderField: "Authorization")
return URLSession.shared.dataTask(.promise, with: request)
}.map { session -> Data in
return session.data
}.compactMap { data -> Promise<T> in
try JSONDecoder().decode(T.self, from: data)
}
}
Maybe it's a bit late for the answer, but I hope it can help some coders who are new to PromiseKit like myself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With