I have decided to upgrade PromiseKit pod form 4.5.x to 6.x.x in my project. During migration process I met an problem which I not 100% sure I solved it in proper way.
Take a look on my sample code from PromiseKit 4.5:
func fetchSettings(forAnimalsGuids animalsGuids: [String]) -> Promise<[JSON]> {
if animalsGuids.isEmpty {
return .value([])
}
let packageSize = 100
let animalsPackages = animalsGuids.chunked(chunkSize: packageSize)
return when(fulfilled: animalsPackages.map({ animalsPackage -> Promise<[JSON]> in
let predicates: [GatewayRequestFactoryHelper.Predicate] = animalsPackage.map({ .atomic(.equal("Animal.ObjectGuid", .string($0))) })
let predicate: GatewayRequestFactoryHelper.Predicate? = !predicates.isEmpty ? .or(predicates) : nil
return gatewayConnector.fetchObjects(type: AnimalMilkSetting.self, predicate: predicate)
}))
.then { result in
Promise(value: Array(result.joined()))
}
}
In a line with Promise(value: Array(result.joined()))
I got an error:
Argument labels '(value:)' do not match any available overloads
According to PromiseKit migration guide return Promise(value: foo)
have beed replaced with: return .value(foo)
, so I refactored my code:
func fetchAnimal(forAnimalsGuids animalsGuids: [String]) -> Promise<[JSON]> {
if animalsGuids.isEmpty {
return .value([])
}
let packageSize = 100
let animalsPackages = animalsGuids.chunked(chunkSize: packageSize)
return when(fulfilled: animalsPackages.map({ animalsPackage -> Promise<[JSON]> in
let predicates: [GatewayRequestFactoryHelper.Predicate] = animalsPackage.map({ .atomic(.equal("Animal.ObjectGuid", .string($0))) })
let predicate: GatewayRequestFactoryHelper.Predicate? = !predicates.isEmpty ? .or(predicates) : nil
return gatewayConnector.fetchObjects(type: AnimalMilkSetting.self, predicate: predicate)
}))
.then { result in
.value(Array(result.joined()))
// Promise(value: Array(result.joined()))
}
}
It did not help. Compile showed an error message:
Cannot convert return expression of type 'Promise<_.T>' to return type 'Promise<[JSON]>'
I made some tweaks and finally find a solution which is accepted my compiler:
func fetchAnimal(forAnimalsGuids animalsGuids: [String]) -> Promise<[JSON]> {
if animalsGuids.isEmpty {
return .value([])
}
let packageSize = 100
let animalsPackages = animalsGuids.chunked(chunkSize: packageSize)
return when(fulfilled: animalsPackages.map({ animalsPackage -> Promise<[JSON]> in
let predicates: [GatewayRequestFactoryHelper.Predicate] = animalsPackage.map({ .atomic(.equal("Animal.ObjectGuid", .string($0))) })
let predicate: GatewayRequestFactoryHelper.Predicate? = !predicates.isEmpty ? .or(predicates) : nil
return gatewayConnector.fetchObjects(type: AnimalMilkSetting.self, predicate: predicate)
}))
.then { result in
Promise { $0.fulfill(Array(result.joined())) }
}
}
Could you give me an answer. Did I migrate it in a proper way? Way .value(Array(result.joined()))
does not work?
I think I found an answer by myself. I used map
introduced in PromiseKit 6. From doc:
map
is fed the previous promise value and requires you return a non-promise, ie. a value.
So:
func fetchAnimal(forAnimalsGuids animalsGuids: [String]) -> Promise<[JSON]> {
if animalsGuids.isEmpty {
return .value([])
}
let packageSize = 100
let animalsPackages = animalsGuids.chunked(chunkSize: packageSize)
return when(fulfilled: animalsPackages.map({ animalsPackage -> Promise<[JSON]> in
let predicates: [GatewayRequestFactoryHelper.Predicate] = animalsPackage.map({ .atomic(.equal("Animal.ObjectGuid", .string($0))) })
let predicate: GatewayRequestFactoryHelper.Predicate? = !predicates.isEmpty ? .or(predicates) : nil
return gatewayConnector.fetchObjects(type: AnimalMilkSetting.self, predicate: predicate)
}))
.map {
Array($0.joined())
}
}
I think this solution is better than wrapping result in another Promise. Simply and Swifty.