ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Swift Promise库能兼容async/await吗?wait()桥接机制与迁移策略详解

Swift Promise库能兼容async/await吗?wait()桥接机制与迁移策略详解 Swift Promise库能兼容async/await吗wait()桥接机制与迁移策略详解【免费下载链接】PromiseA Promise library for Swift, based partially on Javascripts A spec项目地址: https://gitcode.com/gh_mirrors/promi/PromiseSwift Promise库基于 JavaScript A 规范在 async/await 时代还能用吗答案是肯定的该库通过 Promise/PromiseExtras.swift 中内置的wait()扩展把回调驱动的 Promise 桥接为可被await的协程值两种异步模型可以平滑共存。本文将带你读懂这套桥接机制的原理并给出一套从回调到 async/await 的分步迁移策略帮助你在旧代码基础上快速、安全地演进。一、为什么还要问「Swift Promise 库 async/await」先快速回顾一下这个库的定位详见 README.md三种状态每个PromiseT都处于pending未决、fulfilled成功带值或rejected失败带错之中状态定义见 Promise/Promise.swift链式组合then支持转换、串联下一个 Promisecatch统一捕获错误行为工具箱Promises.all/race/retry/timeout/zip/kickoff等静态方法让重试、竞速、超时、并行聚合变得像拼积木一样简单源码在 Promise/PromiseExtras.swift对已经写过 async/await 的同学来说then链确实显得啰嗦。但 Promise 库有两个 async/await 给不了的能力结构化的错误恢复recover只针对特定错误类型恢复mapError可以跨域转换错误类型比do/catch更显式可插拔的执行上下文on:参数接受任意ExecutionContext包括库自带的InvalidatableQueue单元复用时可取消回调这是协程模型里不方便表达的技巧所以问题不是要不要抛弃 Promise而是两者如何互相调用。二、wait() 桥接机制让 Promise 变成可 await 的值✅一句话原理wait()用系统提供的withCheckedThrowingContinuation把挂起的协程和Promise 的回调对接起来——Promise 一完成就唤醒等待的协程。完整实现只有十几行available(macOS 12.0.0, iOS 15, watchOS 7, *) public extension Promise { func wait(on queue: DispatchQueue DispatchQueue.main) async throws - Value { try await withCheckedThrowingContinuation { continuation in self.then(on: queue) { value in continuation.resume(with: .success(value)) }.catch(on: queue) { error in continuation.resume(with: .failure(error)) } } } }源码位置Promise/PromiseExtras.swift拆开看有 3 个关键点1. continuation 是「一次性唤醒开关」withCheckedThrowingThrowingContinuation会暂停当前协程并向你交付一个continuation。Promise 成功后调用resume(with: .success)失败后调用resume(with: .failure)协程就在try await处原地醒来。编译期强制 continuation 只能被恢复一次天然杜绝了重复回调问题。2.on:参数决定在哪条队列上恢复回调默认挂在主队列上执行你可以通过try await fetchUsers().wait(on: DispatchQueue.global())改到其他队列。对于要刷新 UI 的场景保持默认即可。3. 系统版本门槛注意available标注需要iOS 15 / macOS 12 / watchOS 7及以上。如果你的项目最低支持版本低于此值需要给调用点加if #available判断或只在兼容层里使用wait()。三、三种互操作用法Promise 与 async/await 双向奔赴用法 1用 await 消费现有 Promise 链旧代码 → 新代码这是最常见的场景业务层已经改成协程但 API 层还返回 Promise。// fetchUsers() 返回 Promise[User]旧接口未改动 func render() async throws { let users try await fetchUsers().wait() // Promise[User] → [User] tableView.reload(with: users) }一行wait()完成切换旧接口零改动。用法 2在 Promise 链内部使用 async/await新代码 → 旧代码反过来then的闭包不能直接await但可以用库提供的kickoff见 Promise/PromiseExtras.swift把一段 async 逻辑包成一个 Promiselet promise Promises.kickoff { () - PromiseData in return Promise { fulfill, reject in Task { do { fulfill(try await someAsyncFetch()) } catch { reject(error) } } } }这样新的协程代码就能继续喂给老的then链和catch错误处理。用法 3把回调式 API 桥进 Promise 世界库的出生技能就是包装 completion 回调官方示例包装URLSession见 README.md 的Creating Promises一节。一旦包成 Promise它就同时获得了then链式能力和wait()协程能力——Promise 成了回调 API 通往协程世界的中转站。四、从回调到 async/await 的分步迁移策略⚠️ 别想着一次性重写。推荐下面这条三步走路线每一步都可独立验证第一步叶子层包装——回调 API → Promise只包装最底层的回调接口网络、存储、系统 API 的 completion 回调让fulfill/reject与回调结果一一对应。此时上层可以自由选择then或wait()。第二步业务层协程化——用 wait() 消费 Promise 链新的业务函数写成async在需要处try await xxx().wait()旧的then调用方继续存在互不干扰。第三步边缘层保留 Promise 门面对第三方 SDK、旧模块暴露的 Promise 型 API 保持不动。最终形成一张清晰的分层场景推荐写法全新业务逻辑直接async/await调用旧 Promise 接口try await promise.wait()在旧 then 链中插入协程Promises.kickoffTask重试 / 超时 / 并行聚合继续用Promises.retry/addTimeout/Promises.all需要按错误类型恢复recover(type:on:)见 Promise/PromiseExtras.swift五、迁移前必须知道的 2 个坑Promise 永不完成 协程永久挂起。continuation 没被唤醒await就一直卡住。防御手段是给关键 Promise 加超时let data try await fetchUsers().addTimeout(10).wait()addTimeout内部用race与一个超时 Promise 竞速实现见 Promise/PromiseExtras.swift超时即拒绝。不要跨 InvalidatableQueue 传递结果。在表格单元格等会复用视图里如果then回调挂在一个已被 invalidate 的队列上且返回了值后续 Promise 会永远停在 pending 状态READMEWarning一节有详细说明。迁移时保留这一约定即可。六、总结Swift Promise 库完全兼容async/await官方内置wait()扩展PromiseExtras.swift第 301–317 行基于withCheckedThrowingContinuation实现一行代码即可互转反方向用Promises.kickoff把协程包回 Promise两种模型双向打通迁移路线包装回调 → 业务层await ...wait()→ 边缘保留 Promise 门面分步演进、随时可验证记住两件事系统版本门槛iOS 15 / macOS 12 起以及给不确定的 Promise 加上addTimeout防挂起依赖与构建信息可参考 Package.swiftSwift Package Manager 集成与 Promises.podspecCocoaPods 集成。掌握这套桥接机制后你就可以安心地让 Promise 与 async/await 在同一工程里各展所长 【免费下载链接】PromiseA Promise library for Swift, based partially on Javascripts A spec项目地址: https://gitcode.com/gh_mirrors/promi/Promise创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表