0

我正在使用带有 scalaFuture.successfulAction.asyncin playframework 2.6:

代码

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")
      }
    }
  }
}

我已按照此处的建议将执行上下文注入未来:

implicit val executor =  scala.concurrent.ExecutionContext.global

为了使控制器异步,我在这里使用了博客文章

错误

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])
4

1 回答 1

3

该方法ws....get()已经返回 a Future,因此您无需将其包装在 aFuture.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")
    }
  }
}
于 2018-01-19T07:36:51.187 回答