FEATURED · 精选文章

Swift Promise库实用技巧:3行代码优雅封装URLSession等回调式API

发布时间 / 2026/8/27 16:01:08
来源 / 创域科博编辑部
栏目 / 资讯中心
Swift Promise库实用技巧:3行代码优雅封装URLSession等回调式API Swift Promise库实用技巧3行代码优雅封装URLSession等回调式API【免费下载链接】PromiseA Promise library for Swift, based partially on Javascripts A spec项目地址: https://gitcode.com/gh_mirrors/promi/Promise项目速览Swift Promise 库Promise是一个轻量、零依赖的 Swift Promise 库灵感部分来自 JavaScript 的 A 规范。它的核心价值把 URLSession 这类回调式 API封装成 Promise 链式调用几行代码即可告别回调地狱Callback Hell让网络请求、数据解析、错误处理一目了然。核心源码仅两个文件Promise.swiftPromise 主实现状态机 then链式调用PromiseExtras.swiftall、race、retry、delay、timeout等实用扩展一、为什么需要 Promise——先看看回调有多难读 用原生 URLSession 发起请求并解析 JSON代码是这样的套娃结构URLSession.shared.dataTask(with: request) { data, response, error in if let error error { // 处理错误 } else if let data data { do { let json try JSONSerialization.jsonObject(with: data) // 用 json } catch { // 再处理一次错误 } } }.resume()问题很明显错误要处理两遍、嵌套层级深、失败后的逻辑分散各处。而用 Promise 改写后结构变成一条直线fetchData(request) // 一个返回 Promise 的封装函数 .then({ data in return try JSONSerialization.jsonObject(with: data) }) .then({ json in self.show(json) }) .catch { error in self.showError(error) // 整条链只有一个错误出口 }这是 Promise 最本质的收益整条异步链路只有一个catch出口且任何一步失败后续then自动跳过。二、核心技巧3行代码封装 URLSession这是全文最重要的一招。Promise 的初始化器init(queue:work:)会给你fulfill成功和reject失败两个闭包用它包一层回调 API 即可func fetchData(_ request: URLRequest) - PromiseData { PromiseData(work: { fulfill, reject in URLSession.shared.dataTask(with: request) { data, _, error in error.map(reject) ?? data.map(fulfill) ?? reject(NilError()) }.resume() }) }配合一个Optional的小扩展项目文档中有推荐写法代码就能压到3行左右struct NilError: Error { } extension Optional { func unwrap() throws - Wrapped { guard let result self else { throw NilError() } return result } }封装之后业务代码就只写纯逻辑fetchData(request) .ensure { data, _ in true } // 状态码检查见下文 .then { try JSONSerialization.jsonObject(with: $0) } .then { print($0) } .catch { print(请求失败\($0)) }两个细节值得注意线程模型work默认在后台队列执行then/catch默认回到主线程无需手动切换队列实现见 Promise.swift 中then方法的on:参数默认值是DispatchQueue.main。块内可随意try/throw库会自动把抛出的错误转成 reject所以JSONSerialization这类抛错 API 直接写在then里就行。三、链式调用then三种玩法then是最核心的方法根据你返回什么它自动做不同的事你在then块里Promise 的行为返回普通值把它作为下一个 Promise 的值转换返回另一个 Promise等待它完成用它的值继续串联不返回Void纯副作用链条结束典型串联示例——取用户列表 → 取第一个用户 → 取他的关注列表fetchUsers() // Promise[User] .then { users in users[0] } // PromiseUser转换 .then { user in fetchFollowers(of: user) } // 串联下一个异步请求 .then { followers in self.followers followers } .catch { error in self.displayError(error) }每次调用then都会返回新的 Promise类型系统会保证上游失败时下游块根本拿不到值这是编译期就保证的不是运行时判断。四、进阶技巧一个方法解决一个常见场景这些实用方法都在 PromiseExtras.swift 中各对应一个高频痛点ensure—— 校验成功结果HTTP 请求没报错不等于成功了404 也要拦住。ensure接受一个判断闭包不通过就转入catchfetchData(request) .ensure { data, http in http.statusCode 200 } .then { data, _ in /* 一定是 200 */ }always—— 无条件收尾无论成功失败都执行最适合停止 loading 动画fetchUsers().then { ... }.always { self.spinner.stopAnimating() }Promises.all—— 并发多请求批量接口并发调用全部完成后拿到结果数组let tasks urls.map { fetchData(URLRequest(url: $0)) } Promises.all(tasks).then { datas in ... }Promises.race—— 竞速多个请求谁先回来用谁的如 CDN 多源取图。Promises.retry(count:delay:)—— 自动重试网络抖动场景一行解决最多重试 N 次。addTimeout—— 超时控制请求超过指定秒数自动失败防止无限等待。recover—— 降级兜底本地读取失败时返回一个新 Promise 去拉服务端数据天然适合本地优先、远端兜底策略。这些组合起来可以写得很漂亮例如缓存读取 超时 重试的组合拳readFromCache() .recover { _ in fetchFromServer() } // 缓存没有兜底拉网络 .addTimeout(3.0) // 3秒内必须有结果 .always { self.hideLoading() }五、安装与上手库零依赖支持 iOS / macOS / tvOS / watchOS / Linux见 Package.swift两种方式任选Swift Package Manager直接把本仓库地址加进 Package 依赖产品名为Promise导入import Promise即可。CocoaPodsPodfile 中添加pod Promises并启用use_frameworks!后执行pod install见 Promises.podspec。最快的上手方式是打开 Promise.playground先 Build 工程再打开 Playground在 Common Patterns 页面把示例前的if false改成if true就能逐个跑通all、race、timeout、retry、recover的效果。行为细节与边界情况可在 PromiseTests 测试用例里对照阅读每个 API 都有对应的断言示范。六、常见问题 FAQQ1then里不返回任何东西会怎样链条到此为止副作用结束不会再产生新的值但若块内throw了错误后面的catch依然能接到。Q2能控制执行队列吗可以。所有接收闭包的方法都有on:参数传任意DispatchQueue即可如.then(on: .global()) { ... }。Q3和 async/await 什么关系Promise 适合一次性成功或失败的场景如单次 HTTP 请求代码组织清晰、组合性强而能多次成功或持续发值的场景推送流、监听更适合 Combine / RxSwift 这类响应式方案。两者不冲突老代码迁移成本远低于全面改 async/await。写在最后Swift Promise 库用不到 700 行核心代码换来了三样东西回调变直线、错误单一出口、异步可组合。封装一次 URLSession3行代码之后所有网络代码都变成干净的then链。项目文档完整见 README.md代码量小非常适合通读源码——它本身就是一堂精炼的 Swift 异步编程课。【免费下载链接】PromiseA Promise library for Swift, based partially on Javascripts A spec项目地址: https://gitcode.com/gh_mirrors/promi/Promise创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻