ActionBuilder 接受 IO[Result] 而不是 Future[Result]
ActionBuilder to accept IO[Result] instead of Future[Result]
我写了一个小例子来在 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 { 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]
你可以使特征扩展 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]
}
这与我们最初定义的几乎完全相同,但不是那么直接。
在ActionComposition.scala兴趣在
组合动作,不提供 基本动作 .
我写了一个小例子来在 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 { 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]
你可以使特征扩展 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]
}
这与我们最初定义的几乎完全相同,但不是那么直接。
在ActionComposition.scala兴趣在 组合动作,不提供 基本动作 .