我在 AWS 上有一个由 HTTP Post 请求触发的 step 函数。该功能可能需要几秒钟才能完成。如果用户将应用程序置于后台,我希望继续执行,并在用户将应用程序放回前台后正确导航到下一个屏幕(如果执行已完成)。
我的 API 客户端端点如下所示:
func connect<OutputType: Decodable>(to request: URLRequestConvertible, decoder: JSONDecoder) -> AnyPublisher<Result<OutputType, Error>, Never> {
var request = request.asURLRequest()
if let token: String = KeychainWrapper.standard.string(forKey: "apiToken") {
request.addValue(token, forHTTPHeaderField: "Authorization")
}
let configuration = URLSessionConfiguration.default
configuration.waitsForConnectivity = true
let session = URLSession(configuration: configuration)
return session.dataTaskPublisher(for: request)
.tryMap({ (data, response) -> Data in
guard let response = response as? HTTPURLResponse else { throw NetworkError.invalidResponse }
guard 200..<300 ~= response.statusCode else {
throw NetworkError.invalidStatusCode(statusCode: response.statusCode)
}
return data
})
.decode(type: OutputType.self, decoder: decoder)
.map(Result.success)
.catch { error -> Just<Result<OutputType, Error>> in Just(.failure(error)) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
我想知道实现这个调用的最佳实践。我目前正在使用下面的 beginBackgroundTask。
func makeRequest() {
DispatchQueue.global(qos: .userInitiated).async {
self.backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Request Name") {
UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
self.backgroundTaskID = .invalid
}
<implementation>
}
}
但是,implementation
仅当我嵌套了 DispatchQueue.main.async 块时才有效,在这些块中我在发出 HTTP 请求后执行更多逻辑(例如在收到响应后确定要导航到下一个屏幕。
这是最好的方法吗?在 DispatchQueue.global 块内可以有几个不同的嵌套 DispatchQueue.main.async 块吗?我应该发布.receive(on: )
到 DispatchQueue.global 吗?