最近在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. Spring框架学习 - 配置

    [资料] ★★☆ Spring 中提供一些Aware相关接口,像是BeanFactoryAware. ApplicationContextAware.ResourceLoaderAware.Servl ...

  2. spry菜单栏(二)

    自定义选项卡式面板构件 尽管使用属性检查器可以简化对选项卡式面板构件的编辑,但是属性检查器并不支持自定义的样式设置任务.您可以修改选项卡式面板构件的 CSS 规则,并创建根据自己的喜好设置样式的构件. ...

  3. (三)在js(jquery)中获得文本框焦点和失去焦点的方法

    在js(jquery)中获得文本框焦点和失去焦点的方法   文章介绍两个方法和种是利用javascript onFocus onBlur来判断焦点和失去焦点,加一种是利用jquery $(" ...

  4. Android控件系列之CheckBox

    学习目的: 1.掌握在Android中如何建立CheckBox 2.掌握CheckBox的常用属性 3.掌握CheckBox选中状态变换的事件(监听器) CheckBox简介: CheckBox和Bu ...

  5. 如何在ubuntu下安装合适的翻译词典

    http://jingyan.baidu.com/article/9faa7231523dd6473c28cb3f.html

  6. gulp使用外部配置文件

    这很有好处,因为它使得任务很干净,并且 config.json 可以被其他的任务运行器(例如grunt)重复利用. config.json { "desktop" : { &quo ...

  7. ubuntu中apt-get安装与默认路径

    一.apt-get 安装 deb是debian linus的安装格式,跟red hat的rpm非常相似,最基本的安装命令是:dpkg -i file.deb或者直接双击此文件 dpkg 是Debian ...

  8. tomcat启动时报:IOException while loading persisted sessions: java.io.EOFException的解决方案

    错误代码如下: 严重: IOException while loading persisted sessions: java.io.EOFException java.io.EOFException ...

  9. 64位Ubuntu 13.04 安装Bochs 2.3.5

    bochs 2.3.5源码编译 网上编译bochs的资料非常多,基本的问题都有解决方案,我重点讲不常见的问题. 基本安装步骤 tar vxzf bochs-2.3.5.tar.gz cd bochs- ...

  10. Codeforces 505 A Mr. Kitayuta's Gift【暴力】

    题意:给出一个字符串,可以向该字符串的任意位置插入一个字母使其变成回文串 因为字符串的长度小于10,枚举插入的字母,和要插入的位置,再判断是否已经满足回文串 #include<iostream& ...