最近在https://github.com/ThoughtWorksInc/rest-rpc上工作,遇到了一个scala隐式转换的问题,简单的说是要实现这么个东西:

implicit def jsonStreamFutureToScalaFuture[Value](jsonStreamFuture: IFuture1[Value]):Future[Value] = ???

把一种类型的Future(com.qifun.jsonStream.rpc.IFuture1)转换成为另一种类型的Future(scala.concurrent.Future)。

其中第一种Future的定义如下:

public interface IFuture1<AwaitResult> {
void start(ICompleteHandler1<AwaitResult> var1);
}

而ICompleteHandler1的定义为:

public interface ICompleteHandler1<AwaitResult> {
void onSuccess(AwaitResult var1); void onFailure(Object var1);
}

彼时对Future和Promise的概念还没有太好的理解,所以把一个未来变换成为另一个未来这种虚无缥缈的东西还是有点想象不来。于是尝试手工实现,

第一版的想法是触发jsonStreamFuture的start方法,传给它一个ICompleteHandler1的实现,然后等到onSuccess方法得到调用的时候,把var1这个结果保存到jsonStreamFutureToScalaFuture这个函数的局部变量中(给其命名为acceptVar吧)。然后再定义一个Future,在Future的实现中不断的检查acceptVar是否有值了,如果有了则返回。这种朴素的想法写出来就是这样:

implicit def jsonStreamFutureToScalaFuture[Value](jsonStreamFuture: IFuture1[Value]):Future[Value] = {
var acceptVar:Any = None jsonStreamFuture.start(new ICompleteHandler1[Value] {
override def onSuccess(value: Value): Unit = acceptVar = value
override def onFailure(ex: scala.Any): Unit = ???
}) new Future {
def onSuccess[U](pf: PartialFunction[Value, Unit]): Unit = {
while (acceptVar == None) {
}
pf(acceptVar.asInstanceOf[Value])
}
}
}

当然这是编译不过的。。。

但即使能够编过,这种while循环的方式也是丑陋的无法接受的。所以开始探索更好的方式,既然在ICompleteHandler1的onSuccss函数中能够得到value,那主动去触发将要返回的那个Future实例内保存的onSuccess的回调如何?想让强类型的语言编译通过比较费劲,所以下面的代码还只是用来demo想法的:

implicit def jsonStreamFutureToScalaFuture[Value](jsonStreamFuture: IFuture1[Value]):Future[Value] = {
var future = new Future(
var successCallBack;
def onSuccess(success: Success): Unit = {
this.successCallBack = success;
}
) jsonStreamFuture.start(new ICompleteHandler1[Value] {
override def onSuccess(value: Value): Unit = future.successCallBack(value)
override def onFailure(ex: scala.Any): Unit = ???
})
future
}

所以当我最后使用Promise来解决类似问题的示例代码时候,我就意识到其思想和上述的第二种方法是类似的,写出来是这样的:

implicit def jsonStreamFutureToScalaFuture[Value](jsonStreamFuture: IFuture1[Value]):Future[Value] = {
val p = Promise[Value]() jsonStreamFuture.start(new ICompleteHandler1[Value] {
override def onSuccess(value: Value): Unit = p success value
override def onFailure(ex: scala.Any): Unit = p failure ex.asInstanceOf[Throwable]
}) p.future
}

好吧,其实本文并没有自己实现一个Promise,不过通过这种重新构造现有概念的方式(当然也是因为自己的无知- -)确实能够帮助对现有概念的理解。

一步步实现Promise的更多相关文章

  1. 8张图让你一步步看清 async/await 和 promise 的执行顺序

    摘要: 面试必问 原文:8张图帮你一步步看清 async/await 和 promise 的执行顺序 作者:ziwei3749 Fundebug经授权转载,版权归原作者所有. 为什么写这篇文章? 说实 ...

  2. 8 张图帮你一步步看清 async/await 和 promise 的执行顺序(转)

    https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651555491&idx=1&sn=73779f84c289d9 ...

  3. JQ中的延迟对象deferred中的promise等的使用

    一.什么是deferred对象? 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作.其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们 ...

  4. 【javascript】异步编年史,从“纯回调”到Promise

    异步和分块——程序的分块执行   一开始学习javascript的时候, 我对异步的概念一脸懵逼, 因为当时百度了很多文章,但很多各种文章不负责任的把笼统的描述混杂在一起,让我对这个 JS中的重要概念 ...

  5. 实现简单的promise

    只考虑成功时的调用,方便理解一下promise的原理promise的例子: 1. 接下来一步步实现一个简单的promise step1:promise 接受一个函数作为构造函数的参数,是立即执行的,并 ...

  6. 一步步学会用docker部署应用(nodejs版)

    一步步学会用docker部署应用 docker是一种虚拟化技术,可以在内核层隔离资源.因此对于上层应用而言,采用docker技术可以达到类似于虚拟机的沙盒环境.这大大简化了应用部署,让运维人员无需陷入 ...

  7. 一起学习造轮子(一):从零开始写一个符合Promises/A+规范的promise

    本文是一起学习造轮子系列的第一篇,本篇我们将从零开始写一个符合Promises/A+规范的promise,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Pr ...

  8. ES6语法(3)—— 用promise()对象优雅的解决异步操作

    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果. ...

  9. ES6之Promise用法详解

    一 前言 本文主要对ES6的Promise进行一些入门级的介绍.要想学习一个知识点,肯定是从三个方面出发,what.why.how.下面就跟着我一步步学习吧~ 二 什么是Promise 首先是what ...

随机推荐

  1. Java:Object类

    objcet类中涉及的多态的扩展性,由于Object是所有类的根类,所以它可以接收任意类型的数据,包括基本数据类型.因为这一特点,它可以对多态性进行扩展. 1.创建一个Demo类来判断类类型 clas ...

  2. C++:流类库与输入输出

    7.2.1 C++的输入输出流 ios:流基类(抽象类) istream:通用输入流类和其他输入流的基类 ostream:通用输出流类和其他输出类的基类 iostream:通用输入输出流类和其他输入输 ...

  3. ExtJs计算两个DateField所间隔的月份(天数) new Date(str) IE游览器提示NaN 处理

    需求:两个DateField控件,分别为开始时间和结束时间.当选择完结束时间后,自动计算这两个时间段所间隔的月或天数. 需要解决的问题: 1.直接使用Ext.getCmp('endDate').get ...

  4. HDU 4622 Reincarnation 后缀自动机

    模板来源:http://blog.csdn.net/zkfzkfzkfzkfzkfzkfzk/article/details/9669747 解法参考:http://blog.csdn.net/dyx ...

  5. 一些practice和总结(转载)

    转自 http://boundary.cc/2013/05/java-app-server-develop/ by JOKER on 2013/05/05 最近状态不是很好,负能量堆到积爆表,静下心来 ...

  6. linux下c程序调用reboot函数实现直接重启【转】

    转自:http://www.blog.chinaunix.net/uid-20564848-id-73878.html linux下c程序调用reboot函数实现直接重启 当然你也可以直接调用syst ...

  7. Cadence ORCAD CAPTURE元件库介绍

    Cadence ORCAD CAPTURE元件库介绍 来源:Cadence 作者:ORCAD 发布时间:2007-07-08 发表评论 Cadence  OrCAD  Capture 具有快捷.通用的 ...

  8. DataGridView中的单元格提示错误信息

    http://stackoverflow.com/questions/7713988/winforms-problems-validating-a-cell-in-a-datagridview

  9. php面试题整理

    PHP经典面试题:(不断跟进补充中...) 1.用PHP打印出前一天的时间格式是2009-02-10 22:21:21(2分) echo date('Y-m-d H:i:s', strtotime(' ...

  10. 《OD学hive》第六周20160731

    一.hive的压缩 1. hadoop的压缩 1)为什么需要压缩 MapReduce的性能瓶颈:网络IO.磁盘IO 数据量:对于MapReduce的优化,最主要.根本就是要能够减少数据量 Combin ...