Reputation: 121
I am currently investigating if I should integrate PromiseKit in an existing project.
My main issue is that I need to implement a business logic that can call up to 5 web-services. Some of them are called depending on the result of previous ones.
My current architecture is based on breaking up the code in several functions with closures that call each other.
I am trying to find out if I could write an easier to manage code with PromiseKit (or anything else).
Here is some pseudo-code of what I need done:
// if true, the phone validation is skipped
let forceRequest = false
// true if a 3rd party web-service has checked the phone number
let isVerified = true
// true if the 3rd party checked the phone number and it is valid
var isValid = false
if !isVerified {
// update value from 3rd party web-service
isValid = isValidPhoneNumberPromise()
}
// If the phone no is invalid stop execution (unless forced)
if !isValid && !force {
throw MyError.error1
}
// web request to create order
createOrderPromise()
// if we have a valid phone number, first send an SMS, then update log
if isValid {
sendSmsPromise()
updateLogPromise()
}
Based on totiG's answer, I came with the following variation:
var isValid = isValid
firstly
{
return Controller.verify(isVerified: isVerified, isValid: isValid)
}
.then { _isValid -> Promise<Int> in
isValid = _isValid
return Controller.createOrder()
}
.then
{ _ -> Promise<Bool> in
if isValid {
return Controller.isSendSms()
}
return Promise (value: true)
}
.then
{ _ -> Promise<Bool> in
if isValid {
return Controller.updateLog()
}
return Promise (value: true)
}
.catch
{ error in
print (error)
}
Upvotes: 2
Views: 2830
Reputation: 5275
Yes you can do this using PromiseKit. I have written a basic example showing what you might need. Remember that you would throw an Error when a step fails and handle those failures in the catch block. In my example the verify step passes, but if isValidPhoneNumber was called it would stop the other steps from running. Where I have put the Promise(value: ) you would put your actual web service calls. If the final step to update log is always required to run, you could put this in a .always
enum Errors: Error {
case invalidPhone
case orderFailed
}
func orderPromise() {
firstly {
self.verify(isVerified: false, force: true)
}.then { _ in
self.createOrder()
}.then { orderNumber in
self.sendSms(orderNumber: orderNumber)
}.then { smsSent in
self.updateLog(smsSent: smsSent)
}.catch { error in
//Do something with the error
}
}
private func verify(isVerified: Bool, force: Bool) -> Promise<Bool> {
if isVerified || force {
return Promise(value: true)
}
return isValidPhoneNumber()
}
private func isValidPhoneNumber() -> Promise<Bool> {
return Promise(error: Errors.invalidPhone) //Assume that this fails, then catch in 'orderPromise' will be run
}
private func createOrder() -> Promise<String> {
//Assume an order number is being passed back to use in the message
return Promise(value: "Order100")
}
private func sendSms(orderNumber: String) -> Promise<Bool> {
return Promise(value: true)
}
private func updateLog(smsSent: Bool) -> Promise<Bool> {
return Promise(value: true)
}
Upvotes: 5