Реактивная асинхронная система обратной связи с RxSwift - PullRequest
1 голос
/ 31 января 2020

Я создаю менеджер вызовов с помощью RXSwift (ReactiveX), который постоянно взаимодействует с API. Диспетчер вызовов содержит несколько объектов, которые сами по себе включают indicator (с указанием информации о состоянии, загруженной из API) и control (запросы для отправки в API).

class CallManagerObjectA() {
  var control = PublishSubject<String>()
  var indicator = BehaviorSubject<String>(value: "string status")
}

В диспетчере вызовов, планировщик регулярно предоставляет новые значения для наблюдаемого индикатора:

<... API response ...>
indicator.onNext(newValue)

Где-то еще в контроллере представления, индикатор будет наблюдаться для метки:

indicator.subscribe(onNext: { label.stringValue = $0 })

Внутри того же контроллера представления пользователь может контролировать состояние объекта с помощью GUI элементов непрерывно:

control.onNext(commandValue)

В диспетчере вызовов контроль будет наблюдаться для вызова API:

control.subscribe(onNext: { (command) in
  // API request call 
})

Пока что так хорошо, это очень хорошо работает с реактивными паттернами. Теперь я ищу хорошее решение для обработки ошибок, если менеджер вызовов распознает ошибки во время взаимодействия API и покажет эти ошибки пользователю в контроллере представления. Я сразу подумал о чем-то вроде этого:

// Call manager recognizes the error
control.onError(error)

...

// Call manager ignores errors for the subscriber
control.retry().ignoreErrors().subscribe(onNext: { (command) in
  // API request call 
})

...

// View controller shows the errors
indicator.subscribe(onNext: { label.stringValue = $0 })
control.subscribe(onError: { print("error", $0) })

Однако это заканчивается бесконечным l oop. Я боюсь, что у меня есть фундаментальная проблема понимания с реактивным программированием, или я упускаю что-то очень важное, но я не могу понять, как обрабатывать ошибки в этой среде реактивных шаблонов.

1 Ответ

1 голос
/ 01 февраля 2020

Основываясь на коде, который вы показали, у вас есть большое недоразумение, не только с тем, как обрабатывать ошибки, но и с тем, как программировать реактивно в целом. Попробуйте посмотреть это видео " Реактивное программирование: почему это важно "

Чтобы ответить на ваш конкретный c вопрос, здесь есть два недоразумения:

  1. Когда вы позвоните control.onError(_:), это будет последний звонок, который вы сможете сделать на control. Как только он выдаст ошибку, он перестанет работать.

  2. Оператор retry() просит свой источник «повторить попытку при ошибке». Если его источник является детерминированным, то он просто будет делать то же самое, что и раньше, и выдавать точно такой же вывод (т. Е. Ту же ошибку, которую он испустил в прошлый раз). В случае PublishSubject он не знает почему onError был вызван. Поэтому лучшее, что он может сделать, это просто снова выдать ошибку.

Честно говоря, я считаю это ошибкой в ​​API, потому что подписка на публичную тему sh, которая выдавала ошибку в какой-то момент в прошлом, просто ничего не должна делать. Но тогда вы не спросите, почему у вас бесконечный l oop. Вместо этого вы спросите, почему ваши control перестали генерировать события.

...