Promissum 是一个用 Swift 编写的承诺库。它具有功能编程中的一些已知函数,如 map
和 flatMap
。
它包含用于处理承诺的有用组合子,例如;用于多个承诺完成的 whenAll
,以及用于一个承诺列表中任何一个完成的 whenAny
。还有它们二进制对应物:whenBoth
和 whenEither
。
当将不同的库的异步操作组合使用时,Promissum 真正大放异彩。目前有一些基本的 UIKit 和 Alamofire 扩展,欢迎为其他库的扩展做出贡献。
这个库有一套广泛的回归测试、文档,并已在多个知名生产应用中使用,详情请见 Q42。
示例
此示例演示了 Alamofire+Promise 和 CoreDataKit+Promise 扩展。
在此示例中,从 Github API 加载 JSON 数据。然后对其进行解析,并存储到 CoreData 中。如果这两个都成功,则向用户显示结果;如果任一个失败,则向用户显示错误描述。
let url = "https://api.github.com/repos/tomlokhorst/Promissum"
Alamofire.request(url).responseJSONPromise()
.map(parseJson)
.flatMap(storeInCoreData)
.then { project in
// Show project name and description
self.nameLabel.text = project.name
self.descriptionLabel.text = project.descr
UIView.animate(withDuration: 0.5) {
self.detailsView.alpha = 1
}
}
.trap { e in
// Either an Alamofire error or a CoreData error occured
self.errorLabel.text = e.localizedDescription
self.errorView.alpha = 1
}
有关此示例的扩展版本,请参阅 FadeExample/ViewController.swift。
取消
Promissum 不支持取消,因为取消与 Promise 的配合并不好。Promise 是未来的 值,值无法取消。如果您确实需要取消(非常常用),可以考虑使用 Tasks 或 Rx 而不是 Promise。我没有与任何 Swift Task/Rx 库的经验,因此无法推荐特定的一个。
尽管如此,如果您想要向 PromiseSource 添加取消功能,您可以使用我写的swift-cancellationtoken 库。然而,这与 Promise 是正交的。
组合器
以下是库提供的部分方法和函数。更多文档可在行内查看。
Promise 实例方法
-
.map(transform: Value -> NewValue)
返回一个包含将函数映射到 Promise 值的结果的 Promise。 -
.flatMap(transform: Value -> Promise<NewValue, Error>)
返回映射函数后结果的扁平化结果。 -
.mapError(transform: Error -> NewError)
返回包含将函数映射到 Promise 错误的结果的 Promise。 -
.flatMapError(transform: Error -> Promise<Value, NewError>)
返回映射 Promise 错误后结果的扁平化结果。 -
.dispatch(on: queue: DispatchQueue)
返回一个新的 Promise,将在指定的 dispatch_queue 上执行所有的回调。请参阅 dispatch queues
处理 Promise 的函数
-
flatten(promise: Promise<Promise<Value, Error>, Error>)
将嵌套的 Promise 的 Promise 扁平化为单一的 Promise。 -
whenBoth(promiseA: Promise<A, Error>, _ promiseB: Promise<B, Error>)
创建一个 Promise,当whenBoth
的两个参数都解析时解决。 -
whenAll(promises: [Promise<Value, Error>])
创建一个 Promise,当所有提供的 Promises 解析时解决。 -
whenEither(promise1: Promise<Value, Error>, _ promise2: Promise<Value, Error>)
创建一个 Promise,当任一参数解析时解决。 -
whenAny(promises: [Promise<Value, Error>])
创建一个 Promise,当任意一个参数的 Promises 解析时解决。
分发队列
Promise 可以在不同的线程或队列上调用处理器。处理器是提供给 .then
、.trap
、.map
和 .flatMap
等方法的闭包。
如果没有指定其他内容,默认情况下,所有处理器都会在主队列上调用。这样,您可以自由地更新 UI,而无需手动调用 dispatch_async
。
然而,改用一个 Promise 使用的分发队列很容易。有两种方法可以实现
- 在创建 PromiseSource 时指定分发队列,例如
let background = DispatchQueue.global(qos: .background)
let source = PromiseSource<Int, Never>(dispatch: .queue(background))
source.promise
.then { x in
// Handler is called on background queue
}
- 或者,使用
.dispatchOn
组合器创建一个新的 Promise
let background = DispatchQueue.global(qos: .background)
somePromise()
.dispatch(on: background)
.then { x in
// Handler is called on background queue
}
为了方便,还有 .dispatchMain
,在背景队列上完成一些工作之后,可以将其移回主队列
let background = DispatchQueue.global(qos: .background)
somePromise()
.dispatch(on: background)
.map { expensiveComputation($0) }
.dispatchMain()
.then { x in
self.updateUi(x)
}
安装
CocoaPods
CocoaPods 是 Cocoa 项目的依赖管理器。您可以使用以下命令安装它:
$ gem install cocoapods
要使用 CocoaPods 在您的 Xcode 项目中集成 Promissum,在您的 Podfile
中指定它
pod 'Promissum'
然后,运行以下命令
$ pod install
版本发布
- 5.0.1 - 2020-10-07 - 将 Promise 方法选项传递给 Alamofire
- 5.0.0 - 2020-08-22 - 将 Alamofire+Promise 更新到 Alamofire 5,需要 iOS 10
- 4.0.0 - 2019-06-10 - 支持 Swift 5.1,使用内置 Result 类型
- 3.2.0 - 2019-04-03 - 弃用
delay
和相关函数 - 3.1.0 - 2018-11-17 - 允许在扩展中使用
- 3.0.0 - 2018-10-02 - 支持 Swift 4.2,移除 CoreDataKit 扩展
- 2.2.0 - 2018-02-09 - 修复偶尔出现的 "在错误队列上执行" 的问题
- 2.1.0 - 2018-01-12 - 支持 watchOS
- 2.0.0 - 2017-11-27 - 支持 Swift 4,线程安全
- 1.0.0 - 2016-09-20 - 支持 Swift 3,需要 iOS 9 & OSX 10.11
- 0.5.0 - 2016-01-19 - 添加用于在不同队列上分发的
dispatchOn
方法 - 0.4.0 - 2015-11-04 - 将 Alamofire+Promise 更新到 Alamofire 3
- 0.3.0 - 2015-09-11 - 支持Swift 2版本,增加了自定义错误类型
- 0.2.4 - 2015-05-31 - 修复示例。更新了CoreDataKit+Promise
- 0.2.3 - 2015-04-13 - 支持Swift 1.2
- 0.2.2 - 2015-03-01 - 支持Mac OS X
- 0.2.1 - 2015-02-16 - 更新到新的CoreDataKit版本
- 0.2.0 - 2015-02-15 - 副作用发生的顺序更好。增加了回归测试。
- 0.1.1 - 2015-05-31 - 增加了
whenAnyFinalized
组合器 - 0.1.0 - 2015-01-27 - 首次公开发布
- 0.0.0 - 2014-10-12 - 为项目Q42的初始私有版本
许可 & 信用
Promissum是由Tom Lokhorst编写的,并可在MIT许可下使用,因此您可以在商业和非商业项目中自由使用它。