2017-04-19 27 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個承諾是可選的。我只有在電話號碼有效時才需要執行它們。如果我不給他們打電話,這不被視爲錯誤。 –