测试已测试 | ✓ |
语言语言 | SwiftSwift |
许可 | MIT |
发布上次发布 | 2017年5月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✗ |
由 Olivier Thierry 维护。
FutureSwift 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中。
pod "FutureSwift"
Future 用于异步并行有效地执行代码块。它们是将来可能存在的值的占位符对象。
这与回调模式相同,但具有更多的灵活性和更简洁的语法和代码风格。Future 是简单对象,包含成功和失败块。它们可以被链式连接,一个可以依赖于另一个,等等。Future附带了一套方法和函数,以提供有效的控制流程。
按照设计,这个库将 Promise 和 Future 模式合并(`Promise` 从 `Future` 继承)。在这个库中,`Promise` 只定义了一个新的初始化器,它接受一个接收 `Promise` 自身的闭包,这样您就可以控制何时解析/拒绝它。
`Future` 的初始化器接受一个不接受任何参数并返回值的块。该块可以抛出异常。如果抛出异常,将使用捕获的异常拒绝未来,否则将使用返回的值解析它。您可以使用它来进行同步工作。
`Promise` 的初始化器接受一个接受 `Promise` 对象的块。然后您负责使用相应的值/错误在该承诺上调用 `resolve(_:)` 或 `reject(_:)`。您可以使用它来进行异步工作。
func fetchUser(id: Int) -> Future<User> {
return Promise { promise in
// Network asynchronous call
Alamofire.request { user, error in
if let error = error {
// Reject
promise.reject(error)
return
}
// Resolve
promise.resolve(user)
// You can continue doing something unrelated
doSomethingUnrelated()
}
}
}
func fetchUser(id: Int) -> Future<Bool> {
return Future {
for i in (0...10000000) {
// Do something expansive...
}
return true
}
}
传入
传入
传入
您可以使用 then(_:)
方法将完成块传递给未来。回调可以是以下之一:
Void -> Void
:忽略 Future
解析出的值,不返回任何内容。A -> Void
:获取未来解析出的值,不返回任何内容。A -> Future<B>
:获取未来解析出的值,并返回一个新的未来。当此未来解析或失败时,未来链将继续。A -> B
:获取未来解析出的值,并返回一个新值。此值是新值,将是传递给未来链其余部分的新值。
注意:这并不会修改未来的原始值。未来的值仅设置一次(当解析时)。
您可以通过传入一个带有一个 ErrorType
参数的闭包来在未来的 fail(_:)
上调用。当链中的某个未来失败时,将使用给定错误调用此块。
Await 允许您在完成过程中阻塞运行线程。这使得多未来的使用更容易阅读和理解。
注意:避免从主线程中调用 await(_:)
。如第###节所述,then(_:)
块被调度在主队列中运行。如果主线程等待未来完成,并且未来需要它的 then(_:)
块被调用才能完成未来的链式调用,它将发生死锁。await(_:)
被设计为可以从任何线程中调用,但不是主线程。
示例
让我们取3个随机函数,执行异步工作。
func f1() -> Future<Void> {
return Future {
NSThread.sleepForTimeInterval(1)
}
}
func f2() -> Future<Void> {
return Future {
NSThread.sleepForTimeInterval(2)
}
}
func f3() -> Future<Void> {
return Future {
NSThread.sleepForTimeInterval(3)
}
}
您可以将未来组合和链式串联如下(使用标准的 then(_:)
/fail(_:)
方法)
func doSomethingAsync() -> Future<Void> {
return f1().then { _ -> Future<Void> in
f2()
}.then { _ -> Future<Void> in
f3()
}.then {
// Everthing's done!
}.fail { error in
// Something went bad
}
}
使用 await
func doSomethingAsync() -> Future<Void> {
return Future {
try await <- f1()
try await <- f2()
try await <- f3()
}
}
现在让我们定义一些彼此有依赖关系的其他函数。在下面的示例中,`f2` 需要由 `f1` 解析出的值来运行,`f3` 需要由 `f2` 解析出的值。
func f1() -> Future<Int> { ... }
func f2(x: Int) -> Future<String> { ... }
func f3(x: String) -> Future<[String]> { ... }
使用标准的 then(_:)/fail(_:)
方法
f1().then { x -> Future<String> in
f2(x)
}.then { y -> Future<[String]> in
f3(y)
}.fail { error in
// Something went bad
}
使用 await(_:)
方法
Future {
let x = try await <- f1()
let y = try await <- f2(x)
let z = try await <- f3(y)
return z
}
或者,如果您真的想酷一点
Future {
try await <- f3 <- f2 <- f1()
}
传入
此库为 CollectionType
提供了一个扩展,其中包含 FutureType
对象。Future
遵循 FutureType
。
CollectionType#all()
方法返回一个新的 Future
。返回的未来将在包含在 self
中的所有未来都解析后解析,并公开未来的值列表。如果一个未来失败,返回的未来将与相同的错误直接失败。
示例
let futures: [Future<Int>] = [f1, f2, ...]
futures.all().then { values in
// All futures completed, values is an Array<Int>
}
CollectionType#any()
方法返回一个新的 Future
。返回的未来将在包含在 self
中的任何未来解析时解析,并公开该值。如果所有未来都失败,则返回的未来也将失败,并返回一个空的错误。
示例
let futures: [Future<Int>] = [f1, f2, ...]
futures.any().then { value in
// All futures completed, values is an Int
}
《CollectionType#reduce()` 方法与标准库中的 reduce 函数类似,但它将一个 futures 列表缩减为一个值列表,而不是值列表。
示例
let futures: [Future<Int>] = [f1, f2, ...]
futures.reduce(0, combine: +).then { value in
// All futures completed, values is an Int
}
《Future#merge(_:)` 方法接收一个 future 实例,并返回一个新的 Future
对象,这个对象将解析为一个元组,包含了 self
和给定 future 的值。如果其中一个 future 失败,返回的 future 也会以相同的错误失败。
let f1: Future<Int> = ...
let f2: Future<String> = ...
f1.merge(f2).then { x, y in
// x is an Int
// y is a String
}
《Future#wrap<A>(_: A.Type)` 方法接收一个任意的 Type
。这在实际情况中很有用,当 future 实际解析一个具有具体类型的值,而 future 的调用者期望另一个类型的值(该值可以被转换为目标类型时)。**注意:您必须确保值可以被转换为给定的类型。否则,您的程序将崩溃**
let f1: Future<String> = ...
let f2 = f1.wrap(AnyObject) // Is now a Future<AnyObject>
Future#wrap()
返回一个新的 future,它解析为 Void
。这在使用 future 实际解析一个具有具体类型的值,但 future 的调用者对此值不感兴趣并期望 时非常有用。
let f1: Future<Int> = ...
let f2 = f1.wrap() // Is now a Future<Void>
Olivier Thierry, [email protected]
FutureSwift 可在 MIT 许可证下使用。有关更多信息,请参阅 LICENSE 文件。