无法理解 Scala 中的 WS 库

Trouble understanding WS library in Scala

我正在尝试使用 play 框架学习 scala,并且我正在尝试完全用 scala 重写一个旧项目以供练习。我已经编写了一条路线,用于注册新订阅者并使用 mandrill 向他们发送一封感谢订阅的电子邮件。我也有一些基本的错误检查。代码如下

  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"-> "info@example.org",
            "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 调用,这样我就可以在发回成功消息之前等待它的响应,因为我想 return 如果 mandrill 发回错误消息给我一个错误.所以我正在尝试做这样的事情:

  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"-> "info@example.org",
            "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")))) 

谁能给我解释一下。我不想使用等待。我只想使用 map 以便获得结果、处理它们然后发回 "Ok" 消息。我正在使用 play 2.3.x 和 scala 2.11

您似乎在 collection.insertmap 块内调用 WSmap 期望你 return 一个 play.api.mvc.Result,但是 WS.post 和你附加的 map,return 一个 Future[play.api.mvc.Result].

鉴于 Future.successful(BadRequest(Json.obj("message"->"Invalid email address"))) returns Future[play.api.mvc.Result] 和你的 collection.insert returns a Future[Future[play.api.mvc.Result]] 常见的推断类型是 Future[Object]

如果您将 collection.insert 上的 map 更改为 flatMap,即表示您打算 return Future[play.api.mvc.Result] 而不是 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"-> "info@example.org",
              "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"))))
  }