Scala之美 - Future & map & flatMap

1. 介绍    

    Scala语言拥有很强的表达能力,语法简洁,很接近人类的思考方式。利用map、flatMap方法做数据转换时,层层递进的演算方式,很像是在画流程图,中间没有停顿,思绪很流畅,不会被无关的变量声明、初始化等琐事打断。Scala中的Future可以让你非常灵活的使用线程,而不需要关注底层的线程管理问题,Scala已经为你处理好一切。下面我们以一个示例来说明,将Future、map和flatMap组合起来会产生多大的威力!

2. 需求描述

    假设我们是一个VPS服务器提供商,现在考虑用户购买了VPS之后,要在控制台上执行创建磁盘快照的操作。系统需要执行的步骤如下:

    1)根据用户id和VPS id,到数据库中分别取出相应记录

    2)检查用户和VPS的状态,如果状态异常,返回报错信息

    3)向消息队列发送一条创建磁盘快照的消息,如果消息发送失败,返回报错信息

    4)执行过程中,如果有异常抛出,直接返回错误页面

    如果只有上面这四条需求,你是不是觉得也太简单了!好吧,下面重头戏来了,为了保证系统的高并发,我们还有第五条要求,

    5)所有的操作都要异步执行,不能阻塞当前处理请求的线程

    小伙伴们,如何实现,你想好了吗?

3. Scala实现

      既要异步执行,又要优雅地处理跨线程异常,看看Scala是如何处理的吧!

def doDiskSnapshot(uid: String, vpsId: String) = Action.async { implicit request => {
    for {
      Some(user) <- getCollection("user").find(Json.obj("_id" -> uid)).one[User] 
      Some(vps)  <- getCollection("vps").find(Json.obj("_id" -> vpsId)).one[Vps] 
    } yield { 
      if(!user.disabled && !vps.disabled){ true } else { false } 
    } 
  }.flatMap{ isValid => 
    if(isValid){ 
      getCollection("snapshot-task").insert(SnapshotTask(...)).map{ wr => 
        if(wr.ok && wr.n == 1){ 
          Ok("操作成功!") 
        } else { 
          Ok("操作失败!") 
        } 
      } 
    } else { 
      Future(Ok("很抱歉,您的操作已被系统拒绝!")) 
    } 
  }.recover{ 
    case t => 
     Ok("很抱歉,发生系统错误,请稍候重试!") 
  } 
}

    第3-4行:从数据库中取出用户和VPS记录

    第6行:   返回状态检查结果

    第8行:   数据传递

    第9行:   检查状态信息

    第10行: 发送消息

    第20行: 错误处理

    整个执行过程一气呵成,去掉方法声明一共22行代码,没有任何拖沓冗余的地方,让人不得不感叹Scala设计之精妙!

    好了,文章到此结束。感兴趣的同学可以猜猜看:假设线程池足够大,上面的代码一共用到了几个线程?答案会在后面公布。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏欧阳大哥的轮子

iOS的MVC框架之控制层的构建(上)

在我前面的两篇文章里面分别对MVC框架中的M层的定义和构建方法进行了深入的介绍和探讨。这篇文章则是想深入的介绍一下我们应该如何去构建控制层。控制层是联系视图层和...

1142
来自专栏积累沉淀

Python快速学习第十二天--生成器和协程

yield指令,可以暂停一个函数并返回中间结果。使用该指令的函数将保存执行环境,并且在必要时恢复。 生成器比迭代器更加强大也更加复杂,需要花点功夫好好理解贯...

8265
来自专栏Danny的专栏

Entity Framework学习笔记——EF简介(一篇文章告诉你什么是EF)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

2183
来自专栏瓜大三哥

​UVM(九)之sequencej机制续1

UVM(九)之sequencej机制续1 当一个sequence启动起来之后,UVM会自动执行sequence的body任务,所以要产生各种和杨的激励,就要写好...

25210
来自专栏Java帮帮-微信公众号-技术文章全总结

Java并发编程,一定要有自己的理解【面试+工作】

编写优质的并发代码是一件难度极高的事情。Java语言从第一版本开始内置了对多线程的支持,这一点在当年是非常了不起的,但是当我们对并发编程有了更深刻的认识和更多的...

1587
来自专栏Golang语言社区

Golang使用pprof监控性能及GC调优

作者:峰云就她了 链接:http://xiaorui.cc/?p=3000 來源:个人博客

3683
来自专栏C/C++基础

腾讯2016春季校园实习招聘技术岗初试(一面)问题汇总(CC++后台)

2016.4.11日广州参加了腾讯的CC++后台技术一面,安全技术类的面试。面试官人很温和,经历了大概70分钟的问答,特将遇到的面试问题汇总如下,自己总结学习,...

831
来自专栏章鱼的慢慢技术路

《算法图解》第五章笔记与课后练习

2164
来自专栏谭广健的专栏

devexpress CLR20r3错误记录

好久没写过winform程序了,用devexpress写了个小工具,连一个本地的数据库,感觉不会出什么异常,连接时就没加捕获,调通之后就没管,因为特殊需求,需要...

2314
来自专栏mini188

Ignite性能测试以及对redis的对比

测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像。测试方法很...

6267

扫码关注云+社区

领取腾讯云代金券