JustNetworking

这是一个用于简化网络层的微型架构库。该库的主要目标是为网络层提供一个简单的抽象,同时保持易用性和可测试性。

这个库不提供任何自定义的 API 调用实现,你必须使用你自己的实现,或者使用像 Alamofire 这样的库。

如何使用?

这个库有三个主要的协议。

  1. Router(路由器)
  2. Request(请求)
  3. Requester(请求器)

Router(路由器)

这个协议用于获取完整的 URL 和请求的 HTTPMethod。默认情况下,使用全局配置中设置的 URL。

你必须首先设置全局 URL

NetworkConfiguration.setCurrentURL(URL(string:"https://www.myApi.com")!)

实现 Router 协议

enum UserRouter: Router {
    case user(id: String)

    var route: Route {
        switch self {
            case .user(let id):
                return Route(path: "user\(id)", method: .get)
            }
      }
}

如果你不想使用全局 URL,你可以通过实现 baseURL 属性来更改。

enum UserRouter: Router {
    case user(id: String)

        var route: Route {
            switch self {
            case .user(let id):
            return Route(path: "user/\(id)", method: .get)
            }
  }

var baseURL: URL {
    return URL(string:"https://www.anotherapi.com")
    }
}

建议不要使用一个枚举来处理所有可能的路径,最好每个域使用一个。例如,如果你有 userpackages 路由,你可以创建两个枚举,一个用于用户路由,另一个用于包路由。

Request(请求)

这个带有关联类型的协议用于抽象 Request 的配置。它有三个关键参数:

  1. responseQueue(响应队列)

你希望回调响应所在的队列。

  1. requestParser(请求解析器)

保存一个函数的属性,该函数将数据解析为关联的类型。

  1. requestFactory(请求工厂)

类型为 RequestFactory 的属性,这是一个用 Router 实现和一个接受 URLRequest 并返回另一个 URLRequest 的函数初始化的结构体。 这个函数的目的是创建组合,允许你为 URLRequest 添加任何你想要的配置。

该库为此协议提供了一个默认实现

    public struct RequestType<Response>: Request {

    public let responseQueue: DispatchQueue

    public let requestParser: RequestParser<Response>

    public let requestFactory: RequestFactory

    public init(responseQueue: DispatchQueue = .global(qos: .default),
            requestFactory: RequestFactory,
            requestParser: @escaping RequestParser<Response>) {
            self.responseQueue = responseQueue
            self.requestParser = requestParser
            self.requestFactory = requestFactory
            }
}

当响应类型为 Decodable 时,它有自己的自定义扩展

extension RequestType where Response: Decodable {

    init(responseQueue: DispatchQueue = .global(qos: .default),
        requestFactory: RequestFactory,
        decoder: JSONDecoder = JSONDecoder()) {
        self.init(responseQueue: responseQueue, requestFactory: requestFactory) {
            return try decoder.decode(Response.self, from: $0)
            }
      }
}

以及当响应为 Void 时

extension RequestType where Response ==  Void {

    init(responseQueue: DispatchQueue = .global(qos: .default),
        requestFactory: RequestFactory) {
        self.init(responseQueue: responseQueue, requestFactory: requestFactory) {
            return ()
        }
    }
}

大多数时候,你将使用此实现来构建你的 Request,但是如果你需要覆盖一些边缘情况,你可以实现该协议并应用你的自定义配置。

为构建 URLRequest 进行组合

该库提供了一个自由函数 compose,它接受一个类型为 RequestBuilder 的可变参数,这只是签名 (URLRequest) -> URLRequest 的类型别名。此函数接受 N 个满足签名的函数,并减少它们,直到获得一个 URLRequest。此函数返回一个 RequestBuilder

例子

    let requestBuilder = compose(addURLParams(["years": "2015"]), addHeaders(["Authorization":"Bearer...."]))
    RequestFactory(router: UserRouter.user(id: "12"), requestBuilder: requestBuilder)

此外,该库还提供了一个自由函数,用于使用 WritableKeyPaths 的优点来改变 URLRequest

set(to: \.cachePolicy, .reloadIgnoringCacheData)

这与 compose 完全兼容,这意味着你可以这样做

compose(set(to: \.cachePolicy, .reloadIgnoringCacheData), set(to: \.networkServiceType, .background))

Requester(请求器)

此协议用于抽象网络客户端,只有一个函数接受一个 Request 和一个闭包作为回调的响应(此闭包具有类型别名 Response<T> 并将 Result 类型作为参数)。

使用 Alamofire 的例子

public func execute<T: Request>(_ request: T, response: @escaping Response<T.Response>)  {

    let urlRequest = request.urlRequest
    Alamofire.request(urlRequest)
            .responseData(queue: request.responseQueue) {
                switch $0.result {
                 case .success(let data):
                do {
                    response(.success(try request.parser(data)))
                } catch {
                    response(.failure(error))
                }
                  case .failure(let error):
                     response(.failure(error))
                  }
             }
        }
}

安装

CocoaPods

只需将以下行添加到 podfile 中

pod `JustNetworking`, `~> 2.0`

许可证

JustNetworking 在 MIT 许可证下发布。有关详细信息,请参见 LICENSE。