2015-05-21 125 views
2

我努力學習斯卡拉與戲劇框架,我想在Scala中完全重寫舊的項目實踐。我寫了一條註冊新訂閱者的路由,並使用mandrill向他們發送了一封感謝電子郵件來訂閱。我也有一些基本的錯誤檢查。代碼如下所示無法理解WS庫在斯卡拉

def create = Action.async(parse.json) { request => 
    request.body.validate[Subscriber].map {subscriber => 
    if (!isValidEmail(subscriber.email)){ 
     Future.successful(BadRequest(Json.obj("message"->"Invalid email address"))) 
    } 
    else{ 
     collection.insert(subscriber).map {lastError => 
     val data = Json.obj(
      "key" -> Play.current.configuration.getString("mandrill.key").get, 
      "template_name" -> "Initial Email", 
      "template_content" -> Json.arr(), 
      "message" -> Json.obj(
      "subject"-> "Example", 
      "from_email"-> "[email protected]", 
      "from_name" -> "example", 
      "to"-> Json.arr(
       Json.obj(
       "email"-> subscriber.email, 
       "name"-> subscriber.fname, 
       "type"-> "to" 
      ) 
      ) 
     ) 
     ) 
     WS.url("https://mandrillapp.com/api/1.0/messages/send-template.json").post(data) 
     Ok(Json.obj("message"->"User created successfully")) 
     } 
     .recover { 
     case e: Throwable => BadRequest(Json.obj("message" -> "A user with email ${subscriber.email} already exists")) 
     } 
    } 
    }.getOrElse(Future.successful(BadRequest(Json.obj("message" -> "Not enough parameters")))) 
} 

這工作,但我希望阻止的WS調用,這樣我可以等待它發回成功的消息之前的響應,因爲我想,如果山魈發送我返回一個錯誤回錯誤。所以,我試圖做這樣的事情:

def create = Action.async(parse.json) { request => 
    request.body.validate[Subscriber].map {subscriber => 
    if (!isValidEmail(subscriber.email)){ 
     Future.successful(BadRequest(Json.obj("message"->"Invalid email address"))) 
    } 
    else{ 
     collection.insert(subscriber).map {lastError => 
     val data = Json.obj(
      "key" -> Play.current.configuration.getString("mandrill.key").get, 
      "template_name" -> "Initial Email", 
      "template_content" -> Json.arr(), 
      "message" -> Json.obj(
      "subject"-> "Example", 
      "from_email"-> "[email protected]", 
      "from_name" -> "example", 
      "to"-> Json.arr(
       Json.obj(
       "email"-> subscriber.email, 
       "name"-> subscriber.fname, 
       "type"-> "to" 
      ) 
      ) 
     ) 
     ) 
     //This line right below doesn't work 
     WS.url("https://mandrillapp.com/api/1.0/messages/send-template.json").post(data).map{response => 
      if (response.status == 200){ 
       Ok(Json.obj("message"->"User created successfully")) 
      } 
      else { 
       BadRequest(Json.obj("message"->"Unknown error")) 
      } 
     } 
     } 
     .recover { 
     case e: Throwable => BadRequest(Json.obj("message" -> "A user with email ${subscriber.email} already exists")) 
     } 
    } 
    }.getOrElse(Future.successful(BadRequest(Json.obj("message" -> "Not enough parameters")))) 
} 

但這又發表了以下錯誤

type mismatch; 
found : scala.concurrent.Future[Object] 
required: scala.concurrent.Future[play.api.mvc.Result] 

上線

}.getOrElse(Future.successful(BadRequest(Json.obj("message" -> "Not enough parameters")))) 

有人可以解釋這一點給我聽聽。我不想用等待。我只是想使用地圖,以便我得到結果,處理它們,然後發回「Ok」消息。我正在使用play 2.3.x和scala 2.11

回答

3

看起來您在塊collection.insert內調用WS。這map期望你返回play.api.mvc.Result,但是WS.postmap你重視它,返回一個Future[play.api.mvc.Result]

鑑於Future.successful(BadRequest(Json.obj("message"->"Invalid email address")))回報Future[play.api.mvc.Result]和你collection.insert回報Future[Future[play.api.mvc.Result]]常見的,推斷的類型是Future[Object]

如果你改變collection.insertmapflatMap,即表明代替play.api.mvc.Result你打算回國Future[play.api.mvc.Result],你應該得到的類型排隊,例如:

def create = Action.async(parse.json) { request => 
    request.body.validate[Subscriber].map { subscriber => 
     if (!isValidEmail(subscriber.email)){ 
     Future.successful(BadRequest(Json.obj("message"->"Invalid email address"))) 
     } else { 
     collection.insert(subscriber).flatMap { lastError => 
      val data = Json.obj(
      "key" -> Play.current.configuration.getString("mandrill.key").get, 
      "template_name" -> "Initial Email", 
      "template_content" -> Json.arr(), 
      "message" -> Json.obj(
       "subject"-> "Example", 
       "from_email"-> "[email protected]", 
       "from_name" -> "example", 
       "to"-> Json.arr(
       Json.obj(
        "email"-> subscriber.email, 
        "name"-> subscriber.fname, 
        "type"-> "to" 
       ) 
      ) 
      ) 
     ) 
      WS.url("https://mandrillapp.com/api/1.0/messages/send-template.json") 
      .post(data).map{ response => 
       if (response.status == 200) { 
       Ok(Json.obj("message"->"User created successfully")) 
       } else { 
       BadRequest(Json.obj("message"->"Unknown error")) 
       } 
      } 
     }.recover { 
      case e: Throwable => BadRequest(Json.obj("message" -> "A user with email ${subscriber.email} already exists")) 
     } 
     } 
    }.getOrElse(Future.successful(BadRequest(Json.obj("message" -> "Not enough parameters")))) 
    } 
+0

非常感謝你的解釋。我沒有意識到使用平面地圖和地圖的差異,這對我有很大的幫助。 – josneville