ios - Swift:依次发送网络请求

标签 ios swift

我想一个接一个地发送请求。等待第一个的响应以发送第二个。

目前我使用这个:

DispatchQueue.global().async {
            let dispatchGroup = DispatchGroup()

            dispatchGroup.enter()
            self.requestOne { _ in
                dispatchGroup.leave()
            }
            dispatchGroup.wait()


            dispatchGroup.enter()
            self.requestTwo { _ in
                dispatchGroup.leave()
            }
            dispatchGroup.wait()


            dispatchGroup.enter()
            self.requestTree { _, url in
                user.profileImage = url?.absoluteString
                dispatchGroup.leave()
            }
            dispatchGroup.wait()


            self.requestFour { error in
                completion(error)
            }
        }

它工作得很好,但我想知道是否有一种方法可以使其更干净,更快捷,而不使用

dispatchGroup.enter()
dispatchGroup.leave()
dispatchGroup.wait()

甚至是在类中包装逻辑的模式

最佳答案

利用组合的简单网络层

这个答案很大程度上受到 this post 的影响。我尽可能删除了不必要的代码,并在需要组成工作 Playground 的地方添加了代码。

Api无关层部分

import Foundation
import Combine

struct Agent {

    func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<T, Error> {
        return URLSession.shared
            .dataTaskPublisher(for: request)
            .tryMap { result -> T in
                return try decoder.decode(T.self, from: result.data)
            }
            .receive(on: DispatchQueue.main)
            .eraseToAnyPublisher()
    }
}

Api相关层部分

enum GithubAPI {
    static let agent = Agent()
    static let base = URL(string: "https://api.github.com")!
}

extension GithubAPI {

    static func repos(username: String) -> AnyPublisher<[Repository], Error> {
        let request = URLRequest(url: base.appendingPathComponent("users/\(username)/repos"))
        return agent.run(request)
    }

    struct Repository: Codable {
        let node_id: String
        let name: String
    }

    static func issues(repo: String, owner: String) -> AnyPublisher<[Issue], Error> {
        let request = URLRequest(url: base.appendingPathComponent("repos/\(owner)/\(repo)/issues"))
        return agent.run(request)
    }

    struct Issue: Codable {
        let url: URL
    }

}

您正在寻找的实际干净且快速的代码

请注意,问题请求取决于 repo 请求。实际请求是通过接收器调用触发的。

let user = "Alamofire"
let repos = GithubAPI.repos(username: user)
let firstRepo = repos.compactMap { $0.first }
let issues = firstRepo.flatMap { repo in
    GithubAPI.issues(repo: repo.name, owner: user)
}
let token = issues.sink(receiveCompletion: { (_) in }) { (issues) in
    print(issues)
}

关于ios - Swift:依次发送网络请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60152082/

相关文章:

swift - 获取 "Use of unresolved identifer"- 找不到 .json 文件?

xcode - 如何让应用程序购买工作

ios - 我正在构建一个简单的 RSS 阅读器应用程序并收到一条奇怪的错误消息

ios - 拆分 Swift 字符串复杂

javascript - 如何解析和显示 TVML 文件中的 JSON 数据

ios - 从 Swift 3 中的字节数组中读取值

ios - 在没有wifi的iOS7中静音通知工作很奇怪

ios - 两个具有相似功能的 View Controller VIPER

ios - 滚动时防止搜索栏消失

ios - 如何在 Eureka Forms 中使用一行来呈现 viewController