Ошибка публикации всегда завершает подписку. Поскольку вы хотите продолжить публикацию после ошибки, вы не можете publi sh вашу ошибку как сбой. Вместо этого вы должны изменить тип вывода вашего издателя. Стандартная библиотека предоставляет Result
, и это то, что вам следует использовать.
func makeStatusPublisher() -> AnyPublisher<Result<StatusResponse, Error>, Never> {
let timer = Timer
.publish(every: 30, tolerance: 10, on: .main, in: .common)
.autoconnect()
.map { _ in true } // This is the correct way to merge with the notification publisher.
let notes = NotificationCenter.default
.publisher(for: UIApplication.willEnterForegroundNotification)
.map { _ in true }
return timer.merge(with: notes)
.flatMap({ _ in
statusResponsePublisher()
.map { Result.success($0) }
.catch { Just(Result.failure($0)) }
})
.eraseToAnyPublisher()
}
Этот издатель периодически генерирует .success(response)
или .failure(error)
и никогда не завершает работу с ошибкой.
Однако вы должны спросить себя, что произойдет, если пользователь неоднократно переключает приложения? Или что, если выполнение запроса API занимает более 30 секунд? (Или оба?) Вы получите несколько запросов, выполняющихся одновременно, и ответы будут обрабатываться в порядке их поступления, который может не совпадать с порядком отправки запросов.
Один из способов исправить это было бы использовать flatMap(maxPublisher: .max(1)) { ... }
, что заставляет flatMap
игнорировать сигналы таймера и уведомления, пока у него есть невыполненный запрос. Но, возможно, было бы даже лучше для него запускать новый запрос для каждого сигнала и отменять предыдущий запрос. Измените flatMap
на map
, а затем switchToLatest
для этого поведения:
func makeStatusPublisher2() -> AnyPublisher<Result<StatusResponse, Error>, Never> {
let timer = Timer
.publish(every: 30, tolerance: 10, on: .main, in: .common)
.autoconnect()
.map { _ in true } // This is the correct way to merge with the notification publisher.
let notes = NotificationCenter.default
.publisher(for: UIApplication.willEnterForegroundNotification)
.map { _ in true }
return timer.merge(with: notes)
.map({ _ in
statusResponsePublisher()
.map { Result<StatusResponse, Error>.success($0) }
.catch { Just(Result<StatusResponse, Error>.failure($0)) }
})
.switchToLatest()
.eraseToAnyPublisher()
}