Scala之美 - Future & map & flatMap

1. 介紹    

    Scala語言擁有很強的表達能力,語法簡潔,很接近人類的思考方式。利用map、flatMap方法作數據轉換時,層層遞進的演算方式,很像是在畫流程圖,中間沒有停頓,思緒很流暢,不會被無關的變量聲明、初始化等雜事打斷。Scala中的Future可讓你很是靈活的使用線程,而不須要關注底層的線程管理問題,Scala已經爲你處理好一切。下面咱們以一個示例來講明,將Future、map和flatMap組合起來會產生多大的威力!
數據庫

2. 需求描述

    假設咱們是一個VPS服務器提供商,如今考慮用戶購買了VPS以後,要在控制檯上執行建立磁盤快照的操做。系統須要執行的步驟以下:
服務器

    1)根據用戶id和VPS id,到數據庫中分別取出相應記錄併發

    2)檢查用戶和VPS的狀態,若是狀態異常,返回報錯信息異步

    3)向消息隊列發送一條建立磁盤快照的消息,若是消息發送失敗,返回報錯信息async

    4)執行過程當中,若是有異常拋出,直接返回錯誤頁面高併發

    若是隻有上面這四條需求,你是否是以爲也太簡單了!好吧,下面重頭戲來了,爲了保證系統的高併發,咱們還有第五條要求,ui

    5)全部的操做都要異步執行,不能阻塞當前處理請求的線程spa

    小夥伴們,如何實現,你想好了嗎?線程

3. Scala實現

      既要異步執行,又要優雅地處理跨線程異常,看看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設計之精妙!

    好了,文章到此結束。感興趣的同窗能夠猜猜看:假設線程池足夠大,上面的代碼一共用到了幾個線程?答案會在後面公佈。

相關文章
相關標籤/搜索