簡體   English   中英

Swift:一個接一個地發送網絡請求

[英]Swift: Sending network request one after another

我想一個接一個地發送請求。 等待第一個響應發送第二個。

目前我使用這個:

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()

甚至是在類中包裝邏輯的模式

與其在請求完成中調用 dispatchGroup.leave() ,不如直接在那里調用下一個請求:

self.requestOne() { [weak self] _ in
   guard let `self` = self else { return }
   self.requestTwo() { [weak self] _ in
      guard ..
      self.requestThree...
   }
}

或者按照評論中的建議,使用像 RxSwift 或 Combine 這樣的框架

編輯:
當某些請求會被其他請求調用時,根據不同的條件,您可以在requestXX方法中檢查條件。 如果不滿足條件,只需調用完成並返回。

func requestTwoIfNeeded(paramsToCheckCondition, completion: ...) {
   guard conditionMet else {
      completion(state)
      return
   }
   self.requestTwo(completion)
}

func sequentialRequests(completion: ...) {
   self.requestOne() { [weak self] _ in
      guard let `self` = self else { return }
      self.requestTwoIfNeeded(conditionalParams) { [weak self] _ in
         ...
      }
   }
}

利用Combine的簡單網絡層

這個答案深受這篇文章的影響。 我盡可能刪除了不必要的代碼,並在需要的地方添加了代碼來組成一個工作游樂場。

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
    }

}

您正在尋找的實際干凈和快速的代碼

請注意,問題請求取決於回購請求。 實際請求由接收器調用觸發。

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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM