Alamofire:如何在全球范围内处理错误 [英] Alamofire : How to handle errors globally

查看:131
本文介绍了Alamofire:如何在全球范围内处理错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与此问题非常相似,但对于Alamofire: AFNetworking:全局处理错误并重复请求

My question is quite similar to this one, but for Alamofire : AFNetworking: Handle error globally and repeat request

如何能够捕获全局错误(通常是401)并在发出其他请求之前处理它(最终如果没有管理就失败了?

How to be able to catch globally an error (typically a 401) and handle it before other requests are made (and eventually failed if not managed) ?

我正在考虑链接一个自定义响应处理程序,但是在应用程序的每个请求上执行它都很愚蠢。

也许是子类化,但是我应该将哪个类子类来处理它?<​​/ p>

I was thinking of chaining a custom response handler, but that's silly to do it on each request of the app.
Maybe subclassing, but which class should i subclass to handle that ?

推荐答案

在oauth流中处理401响应的刷新是相当的考虑到NSURLSessions的并行性,复杂。我花了很多时间构建一个对我们来说非常好的内部解决方案。以下是对如何实现它的一般概念的非常高级别的提取。

Handling refresh for 401 responses in an oauth flow is quite complicated given the parallel nature of NSURLSessions. I have spent quite some time building an internal solution that has worked extremely well for us. The following is a very high level extraction of the general idea of how it was implemented.

import Foundation
import Alamofire

public class AuthorizationManager: Manager {
    public typealias NetworkSuccessHandler = (AnyObject?) -> Void
    public typealias NetworkFailureHandler = (NSHTTPURLResponse?, AnyObject?, NSError) -> Void

    private typealias CachedTask = (NSHTTPURLResponse?, AnyObject?, NSError?) -> Void

    private var cachedTasks = Array<CachedTask>()
    private var isRefreshing = false

    public func startRequest(
        method method: Alamofire.Method,
        URLString: URLStringConvertible,
        parameters: [String: AnyObject]?,
        encoding: ParameterEncoding,
        success: NetworkSuccessHandler?,
        failure: NetworkFailureHandler?) -> Request?
    {
        let cachedTask: CachedTask = { [weak self] URLResponse, data, error in
            guard let strongSelf = self else { return }

            if let error = error {
                failure?(URLResponse, data, error)
            } else {
                strongSelf.startRequest(
                    method: method,
                    URLString: URLString,
                    parameters: parameters,
                    encoding: encoding,
                    success: success,
                    failure: failure
                )
            }
        }

        if self.isRefreshing {
            self.cachedTasks.append(cachedTask)
            return nil
        }

        // Append your auth tokens here to your parameters

        let request = self.request(method, URLString, parameters: parameters, encoding: encoding)

        request.response { [weak self] request, response, data, error in
            guard let strongSelf = self else { return }

            if let response = response where response.statusCode == 401 {
                strongSelf.cachedTasks.append(cachedTask)
                strongSelf.refreshTokens()
                return
            }

            if let error = error {
                failure?(response, data, error)
            } else {
                success?(data)
            }
        }

        return request
    }

    func refreshTokens() {
        self.isRefreshing = true

        // Make the refresh call and run the following in the success closure to restart the cached tasks

        let cachedTaskCopy = self.cachedTasks
        self.cachedTasks.removeAll()
        cachedTaskCopy.map { $0(nil, nil, nil) }

        self.isRefreshing = false
    }
}

这里要记住的最重要的事情是你不想跑回复每一个401的刷新调用。大量请求可以同时竞赛。因此,您希望对第一个401执行操作,并将所有其他请求排入队列,直到401成功为止。我上面概述的解决方案确实如此。通过 startRequest 方法启动的任何数据任务将在达到401时自动刷新。

The most important thing here to remember is that you don't want to run a refresh call for every 401 that comes back. A large number of requests can be racing at the same time. Therefore, you want to act on the first 401, and queue all the additional requests until the 401 has succeeded. The solution I outlined above does exactly that. Any data task that is started through the startRequest method will automatically get refreshed if it hits a 401.

其他一些这个非常简单的例子中没有考虑的重要事项是:

Some other important things to note here that are not accounted for in this very simplified example are:


  • 线程安全

  • 保证成功或失败关闭电话

  • 存储和获取oauth令牌

  • 解析回复

  • 将解析后的响应转换为适当的类型(泛型)

  • Thread-safety
  • Guaranteed success or failure closure calls
  • Storing and fetching the oauth tokens
  • Parsing the response
  • Casting the parsed response to the appropriate type (generics)

希望这有助于解决问题。

Hopefully this helps shed some light.

这篇关于Alamofire:如何在全球范围内处理错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆