最近在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. iOS:核心动画的详解介绍:CAAnimation(抽象类)及其子类

    核心动画的详解介绍:CAAnimation(抽象类)   1.核心动画基本概念 Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍! 使用它 ...

  2. 调试EF源代码环境配置

    下载EF6的源代码,运行build编译,Nuget会自动下载所需的DLL. 打开EF的工程,可以在EF解决方案下直接新建调试用的项目代码 添加EF引用时选择解决方案中的Entity Framework ...

  3. 应用scikit-learn做文本分类

    文本挖掘的paper没找到统一的benchmark,只好自己跑程序,走过路过的前辈如果知道20newsgroups或者其它好用的公共数据集的分类(最好要所有类分类结果,全部或取部分特征无所谓)麻烦留言 ...

  4. 基于webpivottable做的透视表

    1.绑定数据和配置: var wptConfig=<%= wptConfig%>; webPivotTable.setCsvData(<%=dataFields %>, < ...

  5. linux 实时时钟(RTC)驱动【转】

    转自:http://blog.csdn.net/yaozhenguo2006/article/details/6820218 这个是linux内核文档关于rtc实时时钟部分的说明,此文档主要描述了rt ...

  6. 聚集索引、非聚集索引、聚集索引组织表、堆组织表、Mysql/PostgreSQL对比、联合主键/自增长、InnoDB/MyISAM(引擎方面另开一篇)

    参考了多篇文章,分别记录,如下. 下面是第一篇的总结 http://www.jb51.net/article/76007.htm: 在MySQL中,InnoDB引擎表是(聚集)索引组织表(cluste ...

  7. How to install ruby on mac/ change ruby source in china

    his one is tailor made for the Basix users among you. If you've been itching to try out Ruby and/or ...

  8. CodeForces Round #298 Div.2

    A. Exam 果然,并没有3分钟秒掉水题的能力,=_=|| n <= 4的时候特判.n >= 5的时候将奇数和偶数分开输出即可保证相邻的两数不处在相邻的位置. #include < ...

  9. 30个实用的Linux find命令

    除了在一个目录结构下查找文件这种基本的操作,你还可以用find命令实现一些实用的操作,使你的命令行之旅更加简易.本文将介绍15种无论是于新手还是老鸟都非常有用的Linux find命令 . 首先,在你 ...

  10. BZOJ 1406 密码箱

    直接两层枚举就行了. 避免排序可以用set. #include<iostream> #include<cstdio> #include<cstring> #incl ...