In my app I use Moya and Alamofire (And also Moya/RxSwift and Moya-ObjectMapper) libraries for all network requests and responses.
I would like to handle the response of all types of requests in one handler, but also uniquely handle every request.
For example for any request I can get the response "Not valid Version", I would like to avoid to check in every response if this error arrived.
Is there an elegant way to handle this use case with Moya
?
Apparently that is very simple, You just should create your own plugin. And add it to your Provider instance (You can add it in the init function)
For example:
struct NetworkErrorsPlugin: PluginType {
/// Called immediately before a request is sent over the network (or stubbed).
func willSendRequest(request: RequestType, target: TargetType) { }
/// Called after a response has been received, but before the MoyaProvider has invoked its completion handler.
func didReceiveResponse(result: Result<Moya.Response, Moya.Error>, target: TargetType) {
let responseJSON: AnyObject
if let response = result.value {
do {
responseJSON = try response.mapJSON()
if let response = Mapper<GeneralServerResponse>().map(responseJSON) {
switch response.status {
case .Failure(let cause):
if cause == "Not valid Version" {
print("Version Error")
}
default:
break
}
}
} catch {
print("Falure to prase json response")
}
} else {
print("Network Error = \(result.error)")
}
}
}
I suggest to use generic parametrized method.
class DefaultNetworkPerformer {
private var provider: RxMoyaProvider<GitHubApi> = RxMoyaProvider<GitHubApi>()
func performRequest<T:Mappable>(_ request: GitHubApi) -> Observable<T> {
return provider.request(request).mapObject(T.self)
}
}
DefaultNetworkPerformer
will handle all requests from you Moya TargetType
. In my case it was GitHubApi
. Example usage of this implementation is:
var networkPerformer = DefaultNetworkPerformer()
let observable: Observable<User> = networkPerformer.performRequest(GitHubApi.user(username: "testUser"))
here you 'inform' network performer that response will contain User
object.
observable.subscribe {
event in
switch event {
case .next(let user):
//if mapping will succeed here you'll get an Mapped Object. In my case it was User that conforms to Mappable protocol
break
case .error(let error):
//here you'll get MoyaError if something went wrong
break
case .completed:
break
}
}