在Scala Play(2.6)EssentialFilter中处理对Future完成的依赖

时间:2018-05-03 13:59:10

标签: scala playframework future

假设我有app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" 名为EssentialFilter,其目的是为每个请求添加标头。但是,要确定需要添加的内容,必须调用返回AbcFilter的库。我当前实现它的方式使用Future,因为我需要Await来完成所以我知道如何构造我需要添加的头。以下是实施:

Future

有没有办法在没有import play.api.libs.concurrent.Execution.Implicits.defaultContext import play.api.mvc._ import scala.concurrent.duration.{Duration, _} import scala.concurrent.{Await, Future} class AbcFilter () extends EssentialFilter { def apply(nextFilter: EssentialAction) = new EssentialAction { def apply(requestHeader: RequestHeader) = { // This call returns a future val future: Future[String] = asyncLibrary.doSomething(requestHeader) //Is there any way to avoid using Await here? val futureResult = Await.result[String](future, Duration(5, SECONDS)) val newHeader = "New-Header-Name"-> futureResult //I do need the future to complete in order to create this header! val data = requestHeader.headers.toSimpleMap.toSeq :+ newHeader val newHeaders = new Headers(_headers = data) nextFilter(requestHeader.withHeaders(newHeaders)) } } } 的情况下实现这个?

2 个答案:

答案 0 :(得分:1)

为避免使用Future,请保持在class AbcFilter () extends EssentialFilter { def apply(nextFilter: EssentialAction) = new EssentialAction { def apply(requestHeader: RequestHeader) = { val newHeaderFut: Future[(String, String)] = asyncLibrary.doSomething(requestHeader) .map(s => "New-Header-Name" -> s) val newHeaders: Future[Headers] = newHeaderFut.map(requestHeader.headers.add) val accumulator: Accumulator[ByteString, Result] = nextFilter(requestHeader) accumulator.mapFuture { result => newHeaders.map(h => result.withHeaders(h.headers: _*)) } } } }

的上下文中
{{1}}

答案 1 :(得分:0)

我能够通过使用Filter而不是EssentialFilter并使用flatMap来解决这个问题。 flatMap可以应用于我们在下面的代码示例中得到的第一个未来,但希望这提供了模式的概念。

    class AbcFilter () extends Filter{
      def apply(nextFilter: RequestHeader => Future[Result])
        (requestHeader: RequestHeader): Future[Result] = {
          val newHeaderFut: Future[(String, String)] = asyncLibrary.doSomething(requestHeader)
            .map(s => "New-Header-Name" -> s)
          val newHeaders: Future[Headers] = newHeaderFut.map(requestHeader.headers.add)
          newHeaders.flatMap { h => { nextFilter(requestHeader.withHeaders(newHeaders))
           }
         }                 
       }        
     }      
   } }