【问题标题】:scala.concurrent.Future[play.api.mvc.Result] required: play.api.mvc.Resultscala.concurrent.Future[play.api.mvc.Result] 需要:play.api.mvc.Result
【发布时间】:2017-12-17 16:08:05
【问题描述】:

我想要一个 Action.async,它 (1) 尝试从数据库中获取值。如果数据库不可用,它将尝试连接到另一个资源并 (2) 从那里获取值。因为我使用的两个资源返回 Future,所以我用“recover”关键字将它们分开。我不确定这是否是最好的方法.....但是 recovery{} 里面的语句有一个类型不匹配错误:

  def show(url: String) = Action.async { implicit request: Request[AnyContent] =>
    println("url: " + url)

    val repositoryUrl = RepositoryUrl(url)
    val repositoryId = RepositoryId.createFromUrl(url)

    // Listing commits from the DB
    val f: Future[Seq[Commit]] = commit.listByRepository(repositoryId.toString())
    f.map { f: Seq[Commit] =>
      val json = JsObject(Seq(
        "project URL" -> JsString(url),
        "list of commits" -> Json.toJson(f)))
      Ok(json)
    }.recover {
      case e: scala.concurrent.TimeoutException =>
        // InternalServerError("timeout")
        // Listing commits from the Git CLI
        val github = rules.GitHub(repositoryUrl)
        val seq: Future[Seq[Commit]] = github.listCommits

        seq.map { seq: Seq[Commit] =>
          val json = JsObject(Seq(
            "project URL" -> JsString(url),
            "list of commits" -> Json.toJson(seq)))
          Ok(json)
        }
    }
  }

我在seq.map { seq: Seq[Commit] => 线上收到错误type mismatch; found : scala.concurrent.Future[play.api.mvc.Result] required: play.api.mvc.Result。如果我的未来失败了,如何返回另一个结果?

谢谢!

【问题讨论】:

    标签: scala concurrent.futures playframework-2.6


    【解决方案1】:

    recover 将简单的结果包装在 Future 中(类似于 map),而 recoverWith 期望 Future 作为结果(类似于 flatMap)。 (https://stackoverflow.com/a/36585703/5794617)。所以,你应该使用recoverWith

    def show(url: String): EssentialAction = Action.async { implicit request: Request[AnyContent] =>
      // This future will throw ArithmeticException because of division to zero
      val f: Future[Seq[Int]] = Future.successful(Seq[Int](1, 2, 3, 4 / 0))
      val fResult: Future[JsObject] = f.map { r =>
        JsObject(Seq(
          "project URL" -> JsString(url),
          "list of commits" -> Json.toJson(r)))
      }.recoverWith {
        case e: ArithmeticException =>
          val seq: Future[Seq[Int]] = Future.successful(Seq(1, 2, 3, 4))
    
          seq.map { seq: Seq[Int] =>
            JsObject(Seq(
              "project URL" -> JsString(url),
              "list of commits" -> Json.toJson(seq)))
          }
      }
      fResult.map { r =>
        Ok(r)
      }
    }
    

    【讨论】:

      【解决方案2】:

      Scala Future.recover 有一个签名

      def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U]
      

      尝试改用recoverWith

      def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多