问题描述
我有几个 datataskpublisher,它们从不同的应用程序屏幕向服务器执行请求。如何让它们串行运行?
下面是一个粗略的例子
这是一个执行请求和附加逻辑的服务。
class Service {
var cacheResult: Data?
var cacnellable: AnyCancellable?
static let shared = Service()
func performPost() -> AnyPublisher<Data,URLError> {
let task = URLSession.shared.dataTaskPublisher(for: URL(string: "postURL")!)
.map { (data,_) in data}
.multicast(subject: PassthroughSubject())
cacnellable = task.erasetoAnyPublisher().sink(
receiveCompletion: {_ in },receiveValue: { data in
self.cacheResult = data
})
return task.autoconnect().erasetoAnyPublisher()
}
func performGet() -> AnyPublisher<Data,URLError> {
let task = URLSession.shared.dataTaskPublisher(for: URL(string: "getURL")!)
.map { (data,receiveValue: { data in
self.cacheResult = data
})
return task.autoconnect().erasetoAnyPublisher()
}
}
这是视图
final class GetVC: UIViewController {
let service = Service.shared
var cancellable: AnyCancellable?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
cancellable = service.performGet()
.sink(receiveCompletion: {_ in},receiveValue: { data in
print("Present data")
})
}
}
final class PostVC: UIViewController {
let service = Service.shared
var cancellable: AnyCancellable?
lazy var button: UIButton = {
let btn = UIButton(primaryAction: UIAction(handler: { _ in
self.cancellable = self.service.performPost()
.sink(receiveCompletion: {_ in },receiveValue: { data in
print("Some logic")
})
}))
return btn
}()
}
我需要请求永远不会并行到达服务器
如果“发布任务”完成,“获取任务”开始
谢谢!
解决方法
我做出了这个决定
class Service {
var cacheResult: Data?
var cancellables = Set<AnyCancellable>()
var taskSubject = PassthroughSubject<AnyPublisher<Data,URLError>,Never>()
var taskInProcess: Bool = false
var tasks: [AnyPublisher<Data,URLError>] = [] {
didSet {
if !taskInProcess,let firstTask = tasks.first {
taskInProcess = true
taskSubject.send(firstTask)
}
}
}
static let shared = Service()
init() {
taskSubject
.flatMap { $0 }
.sink(receiveCompletion: { _ in },receiveValue: { _ in
self.taskInProcess = false
self.tasks.removeFirst()
})
.store(in: &cancellables)
}
func performPost() -> AnyPublisher<Data,URLError> {
let task = URLSession.shared.dataTaskPublisher(for: URL(string: url)!)
.map { (data,_) in data}
.multicast(subject: PassthroughSubject())
tasks.append(task.autoconnect().eraseToAnyPublisher())
return task.eraseToAnyPublisher()
}
func performGet() -> AnyPublisher<Data,_) in data}
.multicast(subject: PassthroughSubject())
tasks.append(task.autoconnect().eraseToAnyPublisher())
return task.eraseToAnyPublisher()
}
}