Как загрузить кэшированный контент с помощью Combine? - PullRequest
1 голос
/ 19 октября 2019

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

В основном моя проблема заключается в попытке получить 2b в приведенном ниже псевдоcode.

Шаг 1: Перейти в кэш и проверить наличие кэшированного содержимого
Шаг 2a: Если в кэше ничего нет -> Извлечь материал из API-клиента -> Кэшировать содержимое -> Возвратить извлеченное содержимоеpublisher
Шаг 2b: если кэшированное содержимое -> вернуть кэшированное содержимоеошибка.

Это было лучшее решение, которое я мог придумать, чтобы осчастливить компилятор.
Какую функциональность Combine следует использовать в этом случае?

public func trainStationsPublisher() -> AnyPublisher<[TrainStation], Error> {
    // Create cache publisher
    let cachePublisher = loadTrainStationsFromCache()

    // Create publisher to fetch train stations from API client (map to new object) and update cache.
    let apiPublisher = apiClient.trainStationsPublisher()
        .map { $0.compactMap(TrainStation.init) }
        .handleEvents(receiveOutput: { (trainStations) in
            self.cachedTrainStations = trainStations
        })

    // Check the cache and return the result if it exists, otherwise fetch data from the api client.
    return cachePublisher
        .append(apiPublisher)
        .first()
        .eraseToAnyPublisher()
}

public func loadTrainStationsFromCache() -> AnyPublisher<[TrainStation], Error> {
    return Deferred<AnyPublisher<[TrainStation], Error>> { () -> AnyPublisher<[TrainStation], Error> in
        if let stations = self.cachedTrainStations {

            // This is the best I've managed to come up with.
            // Just mapping a non-existent error in order to get the desired return type. 
            // Note: fatalError() will never ever be executed since Just(stations) will never fail.
            // How am I suppose to return the cached stations in a publisher?

            return Just(stations).mapError { _ -> Error in
                fatalError()
            }
            .eraseToAnyPublisher()
        } else {
            return Empty<[TrainStation], Error>().eraseToAnyPublisher()
        }
    }.eraseToAnyPublisher()
}
...