2017-04-19 28 views
1

我目前正在调查是否应将PromiseKit集成到现有项目中。带有可选承诺的PromiseKit

我的主要问题是我需要实现一个可以调用5个Web服务的业务逻辑。其中一些被调用取决于以前的结果。

我目前的体系结构是基于分解几个函数中的代码来调用对方的闭包。

我想知道我是否可以使用PromiseKit(或其他)编写更易于管理的代码。

这里是我需要做的事情的一些伪代码:

 // 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() 
     } 

基于totiG的答案,我想出了以下变化:

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) 
     } 

回答

0

是的,你可以使用PromiseKit做到这一点。我写了一个基本的例子,显示你可能需要什么。请记住,如果某个步骤失败并在catch块中处理这些失败,则会引发错误。在我的例子中,验证步骤通过,但是如果调用了isValidPhoneNumber,它会阻止其他步骤的运行。在我放置Promise(value:)的地方,你会把你的实际的Web服务调用。如果最后一步更新日志总是需要运行,你可以把它放在一个.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) 
} 
+0

谢谢你的帮助。嗨,我最终使用了您的代码的变体(请参阅问题编辑),请让我知道如果您看到我的方法有任何问题。 –

+0

虽然您的代码确实有效,但您在每个函数中都检查isValid属性是否为true。承诺应该工作,以便下一步只有在前一个有效时才会执行。在我的例子中,你应该做的是在验证失败时返回一个错误(或者你可以抛出一个异常) - 这会导致catch函数运行,并且你不需要担心在其他地方检查isValid。 – totiG

+0

问题是最后2个承诺是可选的。我只有在电话号码有效时才需要执行它们。如果我不给他们打电话,这不被视为错误。 –