1 year ago
#379160
Rush B
How to load results from Realm cache while loading network results in Swift Combine
I am trying to use Combine to load initial results using cache from Realm and then making a network request but keep running into road blocks.
My work in progress code tries to fetch cache then chains the network request. It also tries to catch the correct errors and maps them to return data which is correct. I'm trying to change it to return the cached results first and then fetch network results all at the same time, I don't think currently it does this.
My function in Combine:
func fetch(byCurrency currency: String) -> AnyPublisher<CreditType, DataError> {
let networkPublisher = store.fetch(byCurrency: currency)
guard let cacheStore = self.cacheStore else {
return networkPublisher
}
let cachedPublisher = cacheStore.fetch(byCurrency: currency)
return cachedPublisher
.flatMap { cachedCredit -> AnyPublisher<CreditType, DataError> in
return networkPublisher
.flatMap { networkCredit -> AnyPublisher<CreditType, DataError> in
return cacheStore.createOrUpdate(networkCredit)
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}
.catch { error -> AnyPublisher<CreditType, DataError> in
if case .nonExistent = error {
return networkPublisher
.flatMap { networkCredit -> AnyPublisher<CreditType, DataError> in
return cacheStore.createOrUpdate(networkCredit)
}
.eraseToAnyPublisher()
}
return AnyPublisher(Fail<CreditType, DataError>(error: error))
}
.eraseToAnyPublisher()
}
Function to convert:
func fetch(byCurrency currency: String, completion: @escaping (Result<CreditType, DataError>) -> Void) {
// Use cache storage if applicable
guard let cacheStore = cacheStore else { return store.fetch(byCurrency: currency, completion: completion) }
cacheStore.fetch(byCurrency: currency) {
// Retrieve missing cache data from cloud if applicable
if case .nonExistent? = $0.error {
return self.store.fetch(byCurrency: currency) {
guard let element = $0.value, $0.isSuccess else { return completion($0) }
cacheStore.createOrUpdate(element, completion: completion)
}
}
// Immediately return local response
completion($0)
guard let cacheElement = $0.value, $0.isSuccess else { return }
// Sync remote updates to cache if applicable
self.store.fetch(byCurrency: currency) {
// Validate if any updates that needs to be stored
guard let element = $0.value, cacheElement.amountCents != element.amountCents, $0.isSuccess else { return }
// Update local storage with updated data
cacheStore.createOrUpdate(element) {
guard $0.isSuccess else {
return self.Log(error: "Could not save updated credit locally from remote storage: \(String(describing: $0.error))")
}
// Callback handler again if updated
completion($0)
}
}
}
}
swift
networking
caching
realm
combine
0 Answers
Your Answer