Swift Promise kickoff详解:把throwing函数和Optional无缝接入异步链
【免费下载链接】PromiseA Promise library for Swift, based partially on Javascript's A+ spec项目地址: https://gitcode.com/gh_mirrors/promi/Promise
Promise 是一个用 Swift 编写的轻量级 Promise 库,部分借鉴了 JavaScript 的 A+ 规范。它的Promises.kickoff是整条异步链的“点火器”:当你的链式起点是一个会throw的函数,或者只是一个 Optional 值时,kickoff能让它们无缝接入then异步链,不用手写繁琐的do { } catch { }。
为什么需要 kickoff?
then闭包内部是“安全空间”——你可以自由try、throw,库会自动把异常转换成链的失败(rejection)。但很多场景里,链的第一步就遇到了麻烦:
- 起点是一个
throws的同步函数(比如读文件、解析配置); - 起点是一个
Optional,为nil时你希望整条链优雅失败。
没有kickoff时,你只能先写一段do { } catch { },手动构造成功或失败的 Promise 才能开始链式调用,代码立刻变得臃肿。
kickoff 的两个重载版本
kickoff是Promises命名空间下的静态方法,有两个重载,定义在 Promise+Extras.swift:
| 重载签名 | 适用场景 | 行为 |
|---|---|---|
kickoff<T>(_ block: () throws -> T) | 同步的 throwing 函数 | 立即执行,返回值包装成已成功的 Promise;抛出错误则直接变成已失败的 Promise |
kickoff<T>(_ block: () throws -> Promise<T>) | 需要搭建一个异步链再返回 | 内部实现是Promise(value: ()).then(block),即先进入then安全空间,再把你返回的 Promise 交给链路继续 |
两者都帮你省去了手动Promise(value:)/Promise(error:)的包装。
场景一:把 throwing 函数变成链的第一环
假设loadConfig()是一个会抛出异常的同步函数:
Promises .kickoff { return try loadConfig() } .then { config in // 使用配置 } .catch { error in // 加载失败,在这里统一处理 }throw被自动翻译成链的 rejection,后续的then全部跳过,直接落到catch。这正是测试用例 PromiseKickoffTests.swift 所验证的两个基础行为:成功取值与失败拒绝。
场景二:Optional 无缝接入异步链
README 中推荐的经典组合是kickoff+ 自定义unwrap()。先给 Optional 加一个会抛错的小扩展:
struct NilError: Error { } extension Optional { func unwrap() throws -> Wrapped { guard let result = self else { throw NilError() } return result } }然后在链的起点使用它:
Promises .kickoff { return try candidateValue.unwrap() } .then { value in // 这里一定是非 nil 的 } .catch { error in // candidateValue 为 nil 时会走到这里 }nil被翻译成一个错误,整条链优雅地失败;非nil时则直接进入链式处理,Optional 被“转正”为非 Optional 值。
场景三:起点本身就是异步链
如果第一步要做的不是取值,而是搭建一段异步流程(比如先延时、再请求),用返回Promise的重载:
let promise = Promises .kickoff { return Promises.delay(0.5) .then { return 2 } }kickoff内部等价于Promise(value: ()).then(block)——先创建一个立即成功的“引子” Promise,再把你的闭包挂到then上执行,因此闭包里可以throw,也可以返回任意 Promise 继续衔接。
使用 kickoff 的 3 个注意事项
- 务必接上
catch。起点闭包一旦抛错,Promise 立即进入 rejected 状态,后续所有then都不会执行。 - 同步重载是立即执行的,闭包里的耗时逻辑不会自动切到后台,重活请放到后续的
then块或用Promise(work:)初始化器里做。 - 与 Optional 配合时,
NilError只是约定俗成的哨兵错误,你也可以抛带信息的自定义错误以便在catch中区分“数据缺失”和“数据非法”。
写在最后
kickoff的精髓只有一句话:让“会抛错的起点”和“可能为空的起点”,以和异步起点完全一致的姿态融入 Promise 链。除了kickoff,Promises命名空间还提供all(聚合)、race(竞速)、retry(重试)、zip(配对)等静态方法,都集中在 Promise+Extras.swift 中,值得逐个了解。
【免费下载链接】PromiseA Promise library for Swift, based partially on Javascript's A+ spec项目地址: https://gitcode.com/gh_mirrors/promi/Promise
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考