You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 4中Promise的then、done、catch等块使用方法及问题求助

理解Swift 4中PromiseKit的链式调用(then、done、catch)

嘿,我来帮你搞清楚PromiseKit里的then、done和catch怎么用,顺便解决你获取Promise值时可能遇到的问题~

首先先明确几个核心概念:

  • Promise是用来处理异步操作的工具,它把嵌套的回调变成线性的链式调用,让代码更易读和维护。
  • 每个Promise有三种状态:pending(进行中)、fulfilled(成功完成)、rejected(失败)。
  • 当Promise成功时,会把结果传递给后续的then或done;失败时,会把错误传递给catch。

第一步:修正你的基础定义

首先你的APIError需要遵守Error协议,不然没法作为Promise的错误类型使用:

struct APIError: Error {
    var message: String?
}

第二步:创建一个返回Promise的异步函数

我们先写一个模拟获取用户的异步函数,这是链式调用的起点:

func fetchUser() -> Promise<User> {
    return Promise { seal in
        // 模拟异步API请求(比如网络请求、数据库读取)
        DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
            // 模拟成功获取用户
            let user = User(firstname: "Damodar", lastname: "Shrestha")
            seal.fulfill(user)
            
            // 如果你想模拟错误,可以替换成下面的代码:
            // let error = APIError(message: "Failed to load user data")
            // seal.reject(error)
        }
    }
}

第三步:链式调用多个then、done和catch

现在我们来实现完整的链式调用,看看多个then怎么串联,done和catch的作用:

class ViewController : UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        fetchUser()
            // 第一个then:接收User对象,返回一个新的Promise<String>(获取用户全名)
            .then { user -> Promise<String> in
                return Promise { seal in
                    DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) {
                        let fullName = "\(user.firstname ?? "") \(user.lastname ?? "")"
                        seal.fulfill(fullName)
                    }
                }
            }
            // 第二个then:接收全名,直接返回Int(PromiseKit会自动包装成Promise<Int>)
            .then { fullName -> Int in
                // 这里可以做一些同步处理,比如根据名字获取模拟年龄
                return 28
            }
            // done:链式的终点,处理最终成功结果(不返回Promise)
            .done { age in
                // 注意:如果要更新UI,必须切回主线程
                DispatchQueue.main.async {
                    print("用户年龄:\(age)岁")
                    // 这里可以更新你的UI组件,比如label.text = "Age: \(age)"
                }
            }
            // catch:捕获整个链中任何一步的错误
            .catch { error in
                if let apiError = error as? APIError {
                    print("请求错误:\(apiError.message ?? "未知错误")")
                } else {
                    print("其他错误:\(error.localizedDescription)")
                }
            }
    }
}

关键知识点解析

  1. 多个then的用法:

    • 每个then的闭包会接收上一个Promise成功的结果。
    • 闭包可以返回两种内容:
      • 另一个Promise:用于继续异步操作(比如第一个then返回的Promise)。
      • 普通值:PromiseKit会自动把它包装成Promise<Value>,让链式调用继续(比如第二个then返回的Int)。
  2. done vs then:

    • done是链式调用的终点,它不返回Promise,所以后面不能再接then或done。
    • done适合用来处理最终的成功结果,比如更新UI、保存数据等收尾操作。
  3. catch的作用:

    • catch会捕获整个Promise链中任何一步抛出的错误(不管是seal.reject()触发的,还是闭包里抛出的异常)。
    • 你可以把catch放在链式的最后,统一处理所有错误。
  4. 常见坑点:

    • 忘记切回主线程更新UI:异步操作通常在后台线程执行,更新UI必须回到主线程,否则会崩溃。
    • 自定义错误未遵守Error协议:只有遵守Error的类型才能作为Promise的错误传递。
    • Promise一直处于pending状态:如果忘记调用seal.fulfill()或seal.reject(),Promise会一直卡在进行中,后续的then/done/catch都不会执行。

内容的提问来源于stack exchange,提问作者Damodar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:37:29