Я пытаюсь лучше понять, как использовать 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()
}