前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >未来的邮箱:Promise

未来的邮箱:Promise

作者头像
dhyuan
发布2022-05-30 14:06:50
2970
发布2022-05-30 14:06:50
举报
文章被收录于专栏:响应式编程

按照Erik的介绍,我们可以把Promise当作装载Future对象的邮箱/容器。

可从它的两个方法签名体会下,你可以向邮箱里放成功的数据或者失败的Exception。

代码语言:javascript
复制
def successful[T](result: T): Promise[T]
def failed[T](exception: Throwable): Promise[T]

放了值之后,可以调用Promise的future() 得到一个已经完成了的Future。

Promise最核心的就是这个逻辑:你可以通过Promise.future()得到一个Future对象,而future里的计算结果是在什么其它地方(当然一般情况是在其它线程里、回调代码里)计算好放进去的。

代码语言:javascript
复制
val p = Promise[Int]()
val f = p.future

def produce() = Future {
  Thread.sleep(500)
  p.success(1)
  println("Produce done")
}

def consume() = Future {
  f.foreach(r => println(s"Get $r"))
  println(s"Consume done")
}

produce()
consume()
StdIn.readLine("End?\n")

这段代码打印如下内容,可以看到consume()方法已经执行完了才打印出“Get 1”。

代码语言:javascript
复制
Consume done
End?
Produce done
Get 1

这个也好理解,foreach只是针对future Success的情况提供了callback机制。需要注意的是Future可以通过onComplete, foreach注册多个callback,但是这些callback运行先后以及运行所在线程是没有保证的。这点区别于map、flatMap。

本来想试着用Promise实现 List[Future[T]] 到 Future[List[T]]的转换,找到foldLeft这种方式。如下:

代码语言:javascript
复制
def sequence[T](fts: List[Future[T]]): Future[List[T]] = {
  fts.foldLeft(Future{ List.empty[T]})((acc, ft) => acc.flatMap(ts => ft.map(t => ts :+ t)))
}

画蛇添足地再体验下promise:

代码语言:javascript
复制
def sequenceByPromise[T](fts: List[Future[T]]): Future[List[T]] = {
  val p = Promise[List[T]]()
  val result = p.success(List.empty[T]).future

  fts.foldLeft(result)((acc, ft) => acc.flatMap(ts => ft.map(t => ts :+ t)))
  result
}

下面代码演示了如何把callback风格代码转为Future风格。在Akka actor框架里,如果需要异步的执行代码并且后面的代码需要这个异步执行的结果,我们就可以通过Promise把结果封装到Future里。

代码语言:javascript
复制
trait CallbackBasedApi {
  def computeIntAsync(continuation: Try[Int] => Unit): Unit
}

trait FutureBasedApi {
  def computeIntAsync(): Future[Int]
}

def futurize(callbackBasedApi: CallbackBasedApi): FutureBasedApi = {
  val p = Promise[Int]()

  // 体会下把“Try=>Unit”当做complete的参数。t => p.complete(t)有没有种嵌套的感觉?:)
  callbackBasedApi.computeIntAsync( t => p.complete(t))

  new FutureBasedApi {
    def computeIntAsync() = p.future
  }
}

Reference:

https://docs.scala-lang.org/overviews/core/futures.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 响应式编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档