I have a pseudo RxSwift implementation of a repository pattern that supports offline and remote operations. I'm trying to migrate it from using our homegrown implementation of Dynamic<T>
to using promises from the PromiseKit
library; the code I'm trying to migrate looks like the following:
class Repository {
private var realmRepo: RealmRepo!
private var httpRepo: HTTPRepo!
private var offlineCache: OfflineCache!
func complete(step: Entity, options: Options) -> Dynamic<Entity> {
let result = Dynamic<Entity>()
realmRepo.complete(step: step, options: options).do(onNext: {[result] value in
guard let realmStep = value else {
return result.complete(with: Error.unknown("realm result was `nil`"))
}
self.httpRepo.complete(step: realmStep, options: options).do(onNext: { value in
result.complete(with: value)
}).do(onError: { error in
switch error {
case HTTPRepo.Error.noNetworkConnection(let request):
try? self.offlineCache.add(object: createOfflineObject(request as! URLRequest))
result.complete(with: realmStep)
default:
result.complete(with: error)
}
})
}).do(onError: {[result] error in
result.complete(with: error)
})
return result
}
The Dynamic<T>
class looks like the following (implementation omitted):
class Dynamic<T> {
func `do`(onNext: (T?) -> Void) -> Dynamic<T> // returns `self`
func `do`(onError: (Error) -> Void) -> Dynamic<T> // returns `self`
func complete(with: Error)
func complete(with: T?)
}
I'm trying to rewrite the return values for the repository from Dynamic<Entity>
to Promise<Entity>
, using the PromiseKit library, I'm not sure how to replicate the following chain of events using promises:
- Attempt the Realm call, if it fails send an error to the returned dynamic object (or fail the promise)
- If the
RealmRepo.complete
call succeeded, then attempt theHTTPRepo.complete
call. - If the
HTTPRepo.complete
call succeeds then emit a "next" value to the dynamic (promise succeeds) - If the
HTTPRepo.complete
call fails then catch the error which will have the failure reason and if it was a lack of network connection then perform another call to theOfflineCache.add
method and resolve the Dynamic value with the result from theRealmRepo.complete
call.
So far I've managed the following:
import PromiseKit
// ... other code ...
class Repository {
// ... repository fields ...
func complete(step: Entity, options: Options) -> Promise<Entity> {
return self.realmRepo.complete(step: step, options).then {
return self.httpRepo.complete(step: $0, options: options)
}.catch { error in
switch error {
case HTTPRepo.Error.noNetworkConnection(let request):
try? self.offlineCache.add(object: createOfflineObject(request as! URLRequest))
default:
result.complete(with: error)
}
}
}
}
Such code gives me a compile error in the catch
block, I'm not even sure of how I'd handle or recover from the error that httpRepo
would return if no connection is present.
Any help is really appreciated!