当前位置:K88软件开发文章中心编程语言SQLscala → 文章内容

Finagle 介绍

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-19 4:45:24

由 Shaodengdeng 创建, 最后一次修改 2016-08-12 Finagle 介绍Finagle-Friendly REPL我们将要讨论的不是标准 Scala 的代码。如果你喜欢使用 REPL 学习,你可能想知道如何获得一个加入 Finagle 及其依赖的 Scala REPL。你可以在这里获取 Finagle 源代码。如果你在 finagle 目录下有 Finagle 的源代码,你可以通过下面的命令得到一个控制台$ cd finagle$ ./sbt "project finagle-http" console ...build output...scala>FuturesFinagle 使用 com.twitter.util.Future [1]编码延迟操作。Future 是尚未生成的值的一个句柄。Finagle 使用 Future 作为其异步 API 的返回值。同步 API 会在返回前等待结果;但是异步 API 则不会等待。例如,个对互联网上一些服务的HTTP请求可能半秒都不会返回。你不希望你的程序阻塞等待半秒。“慢”的 API 可以立即返回一个 Future,然后在需要解析其值时“填充”。val myFuture = MySlowService(request) // returns right away ...do other things...val serviceResult = myFuture.get() // blocks until service "fills in" myFuture在实践中,你不会发送一个请求,然后在几行代码后调用 myFuture.get。Future 提供了注册回调的方法,在值变得可用时会调用注册的回调函数。如果你用过其他异步 API,当看到“回调”你也许会畏缩。你可能会联想到他们难以辨认的代码流,被调用的函数藏在离调用处远远的地方。但是,Future 可以利用 Scala 中“函数是一等公民”的特性编写出更可读的代码流。你可以在调用它的地方简单地定义一个处理函数。例如,写代码调度请求,然后“处理”回应,你可以保持代码在一起:val future = dispatch(req) // returns immediately, but future is "empty"future onSuccess { reply => // when the future gets "filled", use its value println(reply)}你可以在 REPL 中用体验一下 Future。虽然不是学习如何在实际代码中使用他们的好方法,但可以帮助理解 API。当你使用 REPL,Promise 是一个方便的类。它是 Future 抽象类的一个具体子类。你可以用它来创建一个还没有值的 Future。scala> import com.twitter.util.{Future,Promise}import com.twitter.util.{Future, Promise}scala> val f6 = Future.value(6) // create already-resolved futuref6: com.twitter.util.Future[Int] = com.twitter.util.ConstFuture@c63a8afscala> f6.get()res0: Int = 6scala> val fex = Future.exception(new Exception) // create resolved sad futurefex: com.twitter.util.Future[Nothing] = com.twitter.util.ConstFuture@38ddab20scala> fex.get()java.lang.Exception ... stack trace ...scala> val pr7 = new Promise[Int] // create unresolved futurepr7: com.twitter.util.Promise[Int] = Promise@1994943491(...)scala> pr7.get() ...console hangs, waiting for future to resolve...Ctrl-CExecution interrupted by signal.scala> pr7.setValue(7)scala> pr7.get()res1: Int = 7scala>在实际代码中使用 Future 时,你通常不会调用 get,而是使用回调函数。get 仅仅是方便在 REPL 修修补补。顺序组合Future 有类似集合 API 中的组合子(如 map, flatMap) 。回顾一下集合组合子,它让你可以表达如 “我有一个整数 List 和一个 square 函数:map 那个列表获得整数平方的列表”这样的操作。这种表达方式很灵巧;你可以把组合子函数和另一个函数放在一起有效地组成一个新函数。面向 Future 的组合子可以让你这样表达:“我有一个期望整数的 Future 和一个 square 函数:map 那个 Future 获得一个期望整数平方的 Future”。如果你在定义一个异步 API,传入一个请求值,你的 API 应该返回一个包装在 Future 中的响应。因此,这些把输入和函数加入 Future 的组合子是相当有用的:它们帮助你根据其它异步 API 定义你自己的异步 API。最重要的 Future 的组合子是 flatMap[2]:def Future[A].flatMap[B](f: A => Future[B]): Future[B]flatMap 序列化两个 Future。即,它接受一个Future和一个异步函数,并返回另一个 Future。方法签名中是这样写的:给定一个 Future 成功的值,函数f提供下一个 Future。如果/当输入的 Future 成功完成,flatMap 自动调用f。只有当这两个 Future 都已完成,此操作所代表的 Future才算完成。如果任何一个 Future 失败,则操作确定的 Future 也将失败。这种隐交织的错误让我们只需要在必要时来处理错误,所以语法意义很大。flatMap 是这些语义组合子的标准名称。如果你有一个 Future 并且想在异步 API 使用其值,使用 flatMap。例如,假设你有一个 Future[User],需要一个 Future[Boolean]表示用户是否已被禁止。有一个 isBanned 的异步 API 来判断一个用户是否已被禁止。此时可以使用 flatMap :scala> import com.twitter.util.{Future,Promise}import com.twitter.util.{Future, Promise}scala> class User(n: String) { val name = n }defined class Userscala> def isBanned(u: User) = { Future.value(false) }isBanned: (u: User)com.twitter.util.Future[Boolean]scala> val pru = new Promise[User]pru: com.twitter.util.Promise[User] = Promise@897588993(...)scala> val futBan = pru flatMap isBanned // apply isBanned to futurefutBan: com.twitter.util.Future[Boolean] = Promise@1733189548(...)scala> futBan.get() ...REPL hangs, futBan not resolved yet...Ctrl-CExecution interrupted by signal.scala> pru.setValue(new User("prudence"))scala> futBan.get()res45: Boolean = falsescala>同样,如果要在 Future 中应用一个同步函数,可以使用 map。例如,假设你有一个 Future[RawCredentials] 需要一个 Future[Credentials]。你有一个的同步的 normalize 函数将 RawCredentials 转换成 Credentials。可以使用 map:scala> class RawCredentials(u: String, pw: String) { | val username = u | val password = pw | }defined class RawCredentialsscala> class Credentials(u: String, pw: String) { | val username = u | val password = pw

[1] [2] [3] [4] [5]  下一页


Finagle 介绍