Scala ActionBuilder接受IO[Result],而不是未来的[Result]
我编写了一个小示例,在play框架中使用scalaz的IO monad。以下示例按预期工作:Scala ActionBuilder接受IO[Result],而不是未来的[Result],scala,scalaz,playframework-2.3,Scala,Scalaz,Playframework 2.3,我编写了一个小示例,在play框架中使用scalaz的IO monad。以下示例按预期工作: object IOAction { def apply(action:IO[Result]):Result = action.unsafePerformIO } class ExampleController extends Controller { val now:IO[DateTime] = IO { DateTime.now } def index = Action { reque
object IOAction {
def apply(action:IO[Result]):Result = action.unsafePerformIO
}
class ExampleController extends Controller {
val now:IO[DateTime] = IO { DateTime.now }
def index = Action { request =>
IOAction {
now.map { dateTime => Ok(views.html.index(dateTime)) }
}
}
}
但是,我想知道使用play ActionBuilder是否会导致API稍微不那么冗长。理想情况下,我想写:
class ExampleController extends Controller {
val now:IO[DateTime] = IO { DateTime.now }
def index = IOAction { request =>
now.map { dateTime => Ok(views.html.index(dateTime)) }
}
}
我被卡住了,因为invokeBlock
函数似乎固定为Future[Result]
类型
def invokeBlock[A](request: R[A], block: P[A] => Future[Result]): Future[Result]
有人知道IOAction与Action行为相同的解决方法吗(即可选的请求参数和正文解析器)?如果重新定义
IOAction
,后一个示例不应该工作吗
object IOAction {
def apply(io: Request[AnyContent] => IO[Result]): Action[AnyContent] =
Action { (request: Request[AnyContent]) => io(request).unsafePerformIO }
}
在Controller
对象中,您可以执行以下操作
def foo(): Handler = IOAction { request =>
Ok("foo").point[IO]
}
也就是说,Future
是异步(IO)计算,其中IO
是同步的。因此,从IO
到Future
的转换非常容易
IO
和ActionBuilder
的组合并不能真正起作用。
ActionBuilder
并没有考虑到IO
。它有
final def apply(block: ⇒ Result): Action[AnyContent]
final def apply(block: (R[AnyContent]) ⇒ Result): Action[AnyContent]
final def async(block: ⇒ Future[Result]): Action[AnyContent]
final def async(block: R[AnyContent]) ⇒ Future[Result]): Action[AnyContent]
您可以制作一个trait扩展ActionBuilder[R]
并提供,比如:
final def io(block: => Result): Action[AnyContent]
final def io(block R[AnyContent] => Result): Action[AnyContent]
然后你可以定义:
object IOAction extends IOActionBuilder[Request] { /* ... */ }
并将其用作:
def foo = IOAction.io { request =>
Ok("foo").point[IO]
}
这与我们最初定义的几乎完全相同,但不是那么直接
兴趣在于
编写动作,而不是提供基本动作。您确定使用play-2.0,而不是play-2.2或play-2.3吗?我使用的是play 2.3.7。如果您也想访问请求参数,则第一种解决方案不起作用,第二种解决方案也不起作用,因为要将IOAction与ActionBuilder结合使用,IOAction的
io
参数应该是Action[A]
类型。见: