带有可选承诺的 PromiseKit

Posted

技术标签:

【中文标题】带有可选承诺的 PromiseKit【英文标题】:PromiseKit with optional promises 【发布时间】:2017-04-19 14:28:20 【问题描述】:

我目前正在调查是否应该将 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)
        

【问题讨论】:

【参考方案1】:

是的,您可以使用 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)

【讨论】:

感谢您的帮助。嗨,我最终使用了您的代码的变体(请参阅问题编辑),如果您发现我的方法有任何问题,请告诉我。 虽然您的代码确实有效,但您正在检查每个 then 函数中的 isValid 属性是否为真。 Promise 应该起作用,以便只有在前一个步骤有效时才会执行下一步。在我的示例中,您应该做的是在验证失败时返回错误(或者您可以抛出异常) - 这将导致 catch 函数运行,您无需担心在其他任何地方检查 isValid。 问题是最后两个承诺是可选的。只有当电话号码有效时,我才需要执行它们。如果我不打电话给他们,这不会被视为错误。

以上是关于带有可选承诺的 PromiseKit的主要内容,如果未能解决你的问题,请参考以下文章

错误:未捕获(承诺):覆盖不存在(离子可选)

等待内部带有承诺的 forEach 完成

带有 FileReader() 的 Javascript 承诺

带有承诺的while循环

带有多个猫鼬查找的foreach循环后的javascript承诺

javascript 带有取消的多个承诺链