#multithreading #nsurlsession #combine #nsurlsessiondatatask
Вопрос:
У меня есть несколько 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, _) in data}
.multicast(subject: PassthroughSubject())
cacnellable = task.eraseToAnyPublisher().sink(
receiveCompletion: {_ in },
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
}()
}
Мне нужно, чтобы запросы никогда не отправлялись на сервер параллельно
Если «отправить задание» завершено, начнется «получить задание» .
Спасибо!
Ответ №1:
Я пришел с этим решением
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: amp;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, 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()
}
}