Как объединить два издателя с разными типами ошибок в Combine - PullRequest
1 голос
/ 03 октября 2019

Я следую шаблону в своем коде Rx, у меня обычно есть триггер Observable, который я использую для создания другого Observable для сетевого запроса. Упрощенный пример:

enum ViewModelError: Error {
  case bang
}

enum DataTaskError: Error {
  case bang
}

func viewModel(trigger: Observable<Void>,
               dataTask: Observable<Result<SomeType, DataTaskError>>) -> Observable<Result<AnotherType, ViewModelError>> {
  let apiResponse = trigger
    .flatMap { dataTask }
}

Эквивалент комбината У меня возникли некоторые проблемы. Я мог бы использовать Result как тип Output и использовать Never как тип Failure, но это похоже на неправильное использование API.

func viewModel(trigger: AnyPublisher<Void, Never>,
               dataTask: AnyPublisher<SomeType, DataTaskError>) -> AnyPublisher<AnotherType, ViewModelError> {
  let apiResponse = trigger
    .flatMap { dataTask }
}

Я получаю ошибку компиляции:

Instance method 'flatMap(maxPublishers:_:)' requires the types 'Never' and 'DataTaskError' be equivalent

Я мог бы использовать mapError и привести обе ошибки к Error, но мне нужно DataTaskError, чтобы иметь возможность создать мой ViewModelError.

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

1 Ответ

2 голосов
/ 04 октября 2019

Если у вас есть издатель с типом сбоя Никогда, вы можете использовать setFailureType(to:) для соответствия типу сбоя другого издателя. Обратите внимание, что этот метод может использоваться только в том случае, если тип ошибки - Никогда, в соответствии с документом. Если у вас есть фактический тип ошибки, вы можете преобразовать ошибку с mapError(_:). Таким образом, вы можете сделать что-то вроде этого:

func viewModel(trigger: AnyPublisher<Void, Never>,
               dataTask: AnyPublisher<SomeType, DataTaskError>) -> AnyPublisher<AnotherType, ViewModelError> {
  trigger
    .setFailureType(to: ViewModelError.self) // Publisher<Void, ViewModelError>
    .flatMap {
        dataTask // Publisher<SomeType, DataTaskError>
            .mapError { _ in ViewModelError.bang } // Publisher<SomeType, ViewModelError>
            .map { _ in AnotherType() } // Publisher<AnotherType, ViewModelError>
    }
.eraseToAnyPublisher()
}
...