FutureSwift 2.0.0rc3

FutureSwift 2.0.0rc3

测试已测试
语言语言 SwiftSwift
许可 MIT
发布上次发布2017年5月
SwiftSwift 版本3.0
SPM支持 SPM

Olivier Thierry 维护。



FutureSwift 2.0.0rc3

  • Olivier Thierry

安装

FutureSwift 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中。

pod "FutureSwift"

用法

Future

Future 用于异步并行有效地执行代码块。它们是将来可能存在的值的占位符对象。

这与回调模式相同,但具有更多的灵活性和更简洁的语法和代码风格。Future 是简单对象,包含成功和失败块。它们可以被链式连接,一个可以依赖于另一个,等等。Future附带了一套方法和函数,以提供有效的控制流程。

Promise

按照设计,这个库将 Promise 和 Future 模式合并(`Promise` 从 `Future` 继承)。在这个库中,`Promise` 只定义了一个新的初始化器,它接受一个接收 `Promise` 自身的闭包,这样您就可以控制何时解析/拒绝它。

  • `Future` 的初始化器接受一个不接受任何参数并返回值的块。该块可以抛出异常。如果抛出异常,将使用捕获的异常拒绝未来,否则将使用返回的值解析它。您可以使用它来进行同步工作。

  • `Promise` 的初始化器接受一个接受 `Promise` 对象的块。然后您负责使用相应的值/错误在该承诺上调用 `resolve(_:)` 或 `reject(_:)`。您可以使用它来进行异步工作。

Future 组合

  • 如果您需要在您的块中执行异步代码(比如您使用 Alamofire,它只提供非阻塞 API 调用)那么使用 `Promise`
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()
    }
  }
}
  • 如果您需要在您的块中执行同步代码,那么使用 `Future`
func fetchUser(id: Int) -> Future<Bool> {
  return Future {
    for i in (0...10000000) {
      // Do something expansive...
    }

    return true
  }
}

传入

简单的 Future

传入

Future 链

传入

使用未来(Futures)

然后(Then)

您可以使用 then(_:) 方法将完成块传递给未来。回调可以是以下之一:

  • Void -> Void:忽略 Future 解析出的值,不返回任何内容。
  • A -> Void:获取未来解析出的值,不返回任何内容。
  • A -> Future<B>:获取未来解析出的值,并返回一个新的未来。当此未来解析或失败时,未来链将继续。
  • A -> B:获取未来解析出的值,并返回一个新值。此值是新值,将是传递给未来链其余部分的新值。

    注意:这并不会修改未来的原始值。未来的值仅设置一次(当解析时)。

失败(Fail)

您可以通过传入一个带有一个 ErrorType 参数的闭包来在未来的 fail(_:) 上调用。当链中的某个未来失败时,将使用给定错误调用此块。

等待(Await)

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()
}

运算符(Operators)

传入

控制流(Control flow)

CollectionType 扩展

此库为 CollectionType 提供了一个扩展,其中包含 FutureType 对象。Future 遵循 FutureType

all

CollectionType#all() 方法返回一个新的 Future。返回的未来将在包含在 self 中的所有未来都解析后解析,并公开未来的值列表。如果一个未来失败,返回的未来将与相同的错误直接失败。

示例

let futures: [Future<Int>] = [f1, f2, ...]

futures.all().then { values in
  // All futures completed, values is an Array<Int>
}

any

CollectionType#any() 方法返回一个新的 Future。返回的未来将在包含在 self 中的任何未来解析时解析,并公开该值。如果所有未来都失败,则返回的未来也将失败,并返回一个空的错误。

示例

let futures: [Future<Int>] = [f1, f2, ...]

futures.any().then { value in
  // All futures completed, values is an Int
}

reduce

《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#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
}

Wrap

《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 文件。