Несоответствие типов ввода и вывода при комбинировании выборки данных - PullRequest
0 голосов
/ 05 марта 2020

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

  • Во-первых, я проверяю, что если я получаю 200, если нет, выдает ошибку.
  • Если я получаю правильные данные, я декодирую их через JSONDecoder, но просто чтобы проверить, есть ли есть какая-то проблема JSON декодирование Я возвращаю объект по умолчанию.
  • Наконец, отображается ошибка, возникающая на первом шаге, но я получаю следующую ошибку в методе экземпляра функции flatMAp

flatMap (maxPublishers: _ :) 'требует, чтобы типы' Publishers.TryMap.Failure '(также называемый' Error ') и' Just.Failure '(также называемый' Never ') были эквивалентны

private func fetchDataFor(urlStr: String) -> AnyPublisher<WeatherData, Error> {
            let url = URL(string: urlStr)!
            return URLSession.shared.dataTaskPublisher(for: url)
                .tryMap({ (data, response)  in
                    let response = (response as? HTTPURLResponse)
                    if response?.statusCode != 200 {
                        throw NSError(domain: "Error", code: response!.statusCode, userInfo: .none)
                    }
                    return data
            })
            .flatMap{ data in
                Just(data)
                    .decode(type: WeatherData.self, decoder: JSONDecoder())
                    .catch{ error in
                        return Just(defaultWeatherData)
                    }
            }
            .mapError{ error in
                return error
            }
            .receive(on: RunLoop.main)
            .eraseToAnyPublisher()
        }

Может кто-нибудь подсказать, что здесь не так, или я использую какой-то неправильный подход. Спасибо

1 Ответ

0 голосов
/ 05 марта 2020

Измените свою функцию следующим образом:

private func fetchDataFor(urlStr: String) -> AnyPublisher<WeatherData, Error> {
    let url = URL(string: urlStr)!
    return URLSession.shared.dataTaskPublisher(for: url)
        .tryMap({ (data, response)  in
            let response = (response as? HTTPURLResponse)
            if response?.statusCode != 200 {
                throw NSError(domain: "Error", code: response!.statusCode, userInfo: .none)
            }
            return data
        })
        .decode(type: WeatherData.self, decoder: JSONDecoder())
        .receive(on: RunLoop.main)
        .eraseToAnyPublisher()
}

Объединение имеет полезный встроенный метод .decode, где вы можете преобразовать свои данные в локальную модель.

Кроме того, хорошей практикой является не использовать .receive(on: RunLoop.main) в методах запроса, а позволить вашему ViewModel / Interactor (просто потребителю ответа) решить, в какой поток он хочет получить ответ.

...