Scala 带PlayFramework 2.6的异步控制器

Scala 带PlayFramework 2.6的异步控制器,scala,asynchronous,playframework,future,executioncontext,Scala,Asynchronous,Playframework,Future,Executioncontext,我在playframework 2.6和scala中使用了Future.successful和Action.async: 代码 package controllers import com.google.inject.Inject import play.api.Configuration import play.api.libs.ws.{WSClient} import play.api.libs.oauth.{ConsumerKey, RequestToken, OAuthCalculat

我在playframework 2.6和scala中使用了
Future.successful
Action.async

代码

package controllers

import com.google.inject.Inject
import play.api.Configuration
import play.api.libs.ws.{WSClient}
import play.api.libs.oauth.{ConsumerKey, RequestToken, OAuthCalculator}
import play.api.mvc.{AbstractController, ControllerComponents}
import play.api.libs.concurrent.CustomExecutionContext

import scala.concurrent.{Future, ExecutionContext}
import akka.actor.ActorSystem

trait MyExecutionContext extends ExecutionContext

class MyExecutionContextImpl @Inject()(system: ActorSystem)
  extends CustomExecutionContext(system, "my.executor") with MyExecutionContext



class Application @Inject() (config: Configuration,
                             ws: WSClient,
                             myExecutionContext: MyExecutionContext,
                             cc: ControllerComponents ) extends AbstractController(cc) {
  def credentials : Option[(ConsumerKey, RequestToken)] = for {
    apiKey <- config.getOptional[String]("twitter.apiKey")
    apiSecret <- config.getOptional[String]("twitter.apiSecret")
    token <- config.getOptional[String]("twitter.token")
    tokenSecret <- config.getOptional[String]("twitter.tokenSecret")
  } yield (
    ConsumerKey(apiKey.toString, apiSecret.toString),
    RequestToken(token.toString, tokenSecret.toString)
  )


  def tweets = Action.async {

    implicit val executor =  scala.concurrent.ExecutionContext.global
    credentials.map {
      case (consumerKey, requestToken) => {

        Future.successful {
          ws
            .url("https://stream.twitter.com/1.1/statuses/filter.json")
            .sign(OAuthCalculator(consumerKey, requestToken))
            .withQueryString("track" -> "reactive")
            .get()
            .map(response => {
              Ok(response.body)
            })
        }
      }
    } getOrElse {
      Future.successful {
        InternalServerError("Twitter credentials are missing")
      }
    }
  }
}
为了使控制器异步,我使用了博客文章

错误

Compiling 1 Scala source to /Users/localuser/Do/play-twitter-example/target/scala-2.12/classes ...
[error] /Users/localuser/Do/play-twitter-example/app/controllers/Application.scala:37:23: overloaded method value async with alternatives:
[error]   [A](bodyParser: play.api.mvc.BodyParser[A])(block: play.api.mvc.Request[A] => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[A] <and>
[error]   (block: play.api.mvc.Request[play.api.mvc.AnyContent] => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] <and>
[error]   (block: => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent]
[error]  cannot be applied to (scala.concurrent.Future[Object])
将1个Scala源代码编译为/Users/localuser/Do/play-twitter-example/target/Scala-2.12/classes。。。
[错误]/Users/localuser/Do/play-twitter-example/app/controllers/Application.scala:37:23:重载的方法值与可选值异步:
[error][A](bodyParser:play.api.mvc.bodyParser[A])(block:play.api.mvc.Request[A]=>scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[A]
[错误](block:play.api.mvc.Request[play.api.mvc.AnyContent]=>scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent]
[错误](block:=>scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent]
[错误]无法应用于(scala.concurrent.Future[对象])
方法
ws….get()
已经返回了一个
未来
,因此您不需要将其包装在
未来。成功
。你可以简单地写

def tweets = Action.async {

  implicit val executor =  scala.concurrent.ExecutionContext.global
  credentials.map {
    case (consumerKey, requestToken) => {

      ws
        .url("https://stream.twitter.com/1.1/statuses/filter.json")
        .sign(OAuthCalculator(consumerKey, requestToken))
        .withQueryString("track" -> "reactive")
        .get()
        .map(response => {
          Ok(response.body)
        })
    }
  } getOrElse {
    Future.successful {
      InternalServerError("Twitter credentials are missing")
    }
  }
}
方法
ws….get()
已经返回了一个
Future
,因此您不需要将它包装在
Future.successful中。你可以简单地写

def tweets = Action.async {

  implicit val executor =  scala.concurrent.ExecutionContext.global
  credentials.map {
    case (consumerKey, requestToken) => {

      ws
        .url("https://stream.twitter.com/1.1/statuses/filter.json")
        .sign(OAuthCalculator(consumerKey, requestToken))
        .withQueryString("track" -> "reactive")
        .get()
        .map(response => {
          Ok(response.body)
        })
    }
  } getOrElse {
    Future.successful {
      InternalServerError("Twitter credentials are missing")
    }
  }
}