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)") } } } }
关键知识点解析
多个
then的用法:- 每个
then的闭包会接收上一个Promise成功的结果。 - 闭包可以返回两种内容:
- 另一个
Promise:用于继续异步操作(比如第一个then返回的Promise)。 - 普通值:PromiseKit会自动把它包装成
Promise<Value>,让链式调用继续(比如第二个then返回的Int)。
- 另一个
- 每个
donevsthen:done是链式调用的终点,它不返回Promise,所以后面不能再接then或done。done适合用来处理最终的成功结果,比如更新UI、保存数据等收尾操作。
catch的作用:catch会捕获整个Promise链中任何一步抛出的错误(不管是seal.reject()触发的,还是闭包里抛出的异常)。- 你可以把
catch放在链式的最后,统一处理所有错误。
常见坑点:
- 忘记切回主线程更新UI:异步操作通常在后台线程执行,更新UI必须回到主线程,否则会崩溃。
- 自定义错误未遵守
Error协议:只有遵守Error的类型才能作为Promise的错误传递。 - Promise一直处于pending状态:如果忘记调用
seal.fulfill()或seal.reject(),Promise会一直卡在进行中,后续的then/done/catch都不会执行。
内容的提问来源于stack exchange,提问作者Damodar
相关产品推荐
相关产品推荐

